Текст
                    В. Н. Касьянов, В. А. Евстигнеев
Графы
в программировании:
обработка, визуализация
и применвние
НАУЧНОЕ ИЗДАНИЕ fbhy

Графы в программировании: обработка, визуализация и применение Касьянов Виктор Николаевич, доктор физико-математических наук, профессор, главный научный сотрудник и заведующий лабораторией "Конструирование и оптимизация программ” Института систем инфор- матики СО РАН им. А. П. Ершова. Известный специалист в области теоре- тического и системного программирования, результаты работ которого воплощены в ряде инструментальных и прикладных программных сис- тем, опубликованы в более 260 научных трудах, в том числе 30 моногра- фиях и учебных пособиях. Член редколлегий международных журналов и сборников, программных комитетов международных конференций, национальных и международных научных обществ. Победитель всех конкурсов грантов Президента РФ для выдающихся ученых. Евстигнеев Владимир Анатольевич, доктор физико-математических наук, профессор, главный научный сотрудник Института систем инфор- матики СО РАН им. А. П. Ершова. Известный специалист в области при- кладной теории графов, результаты работ которого опубликованы в более 160 научных трудах, в том числе 16 монографиях и учебных посо- биях. Неоднократный победитель конкурсов грантов Президента РФ для выдающихся ученых. БХВ-Петербург 198005, Санкт-Петербург, Измайловский пр., 29 E-malt: mall@bhv.ru Internet: www.bhv.ru тел.: (812)251-42-44 факс: (812) 251-12-95 «ssss^ НАУЧНОЕ ИЗДАНИЕ Му*
В. Н. Касьянов В. А. Евстигнеев Графы в программировании: обработка, визуализация и применение Санкт-Петербург «БХВ-Петербург» 2003
УДК 681.3.06+519.6 ББК 32.81 К28 Касьянов В. Н., Евстигнеев В. А. К28 Графы в программировании: обработка, визуализация и применение. — СПб.. БХВ-Петербург, 2003. — 1104 с., ил. ISBN 5-94157-184-4 Книга содержит изложение фундаментальных основ современных ком- пьютерных технологий, связанных с применением теории графов. Приве- дены основные модели, методы и алгоритмы прикладной теории графов. Рассмотрены задачи рисования графов и визуальной обработки графовых моделей. Описаны области приложения, такие как хранение и поиск ин- формации, трансляция и оптимизация программ, анализ, преобразование и распараллеливание программ, параллельная и распределенная обработка информации. В книге используется высокоуровневое описание алгоритмов, позволяющее понять алгоритм на содержательном уровне, оценить пригод- ность его для решения конкретной задачи и осуществить модификацию ал- горитма, не снижая степень математической достоверности окончательного варианта программы. Для научных работников, инженеров, преподавателей, аспирантов и студентов естественно-научных специальностей УДК 681.3.06+519.6 ББК 32.81 Группа подготовки издания: Главный редактор Дам. главного редактора Зав редакцией Редактор Компьютерная верстка Корректор Дизайн обложки Зав. производством Екатерина Кондукова Анатолий Адаменко Григорий Добин Полина Столбова Ольга Сергиенко Зинаида Дмитриева Игоря Цырульникова Николай Тверских Лицензия ИД Nn 02429 от 24.07 00. Подписано в печать 23 05.03. Формат 70> 1001/16. Печать офсетная. Уел. печ л. 89. Тираж 3000 экз. Заказ Ns 202 "БХВ-Петербург" 198005, Санкт-Петербург, Измайловский пр., 29. Гигиеническое заключение на продукцию, товар № 77.99 02.953.Д 001537.03.02 от 13.03.2002 г. выдано Департаментом ГСЭН Минздрава России Отпечатано с готовых диапозитивов в ФГУП ордена Трудового Красного Знамени "Техническая книга" Министерства Российской Федерации по делам печати, телерадиовещания и средств массовых коммуникаций. 198005, Санкт-Петербург, Измайловский пр., 29. ISBN 5-94157-184-4 © Касьянов В. Н., Евстигнеев В. А.. 2003 © Оформление, издательство “ЬХВ-Петербург". 2001
Содержание Введение...............................................................15 ЧАСТЬ I. ОБРАБОТКА И ВИЗУАЛИЗАЦИЯ ГРАФОВ...............................19 Глава 1. Графы и сети................................................ 21 1.1. Неориентированные графы...........................................21 1 1.1. Обыкновенные графы и их свойства............................ 21 1 1.2. Деревья и их основные свойства...............................31 1.1.3. Хордальные графы и их классификация..........................34 1.1.4. Алгоритмы распознавания и раскраски..........................36 1 1.5. Кратчайшие цепи......................... .. .. . 40 1.1.6. Задача о минимальной связке..................................40 1.2. Орграфы и сети....................................................40 1.2.1. Орграфы..................................................... 41 1 2.2. Кратчайшие пути..............................................43 1.2.3. Генерация путей..............................................46 1.2.4. Генерация контуров...........................................48 1 2.5. Сети и задачи о потоках.................................... 50 1 2.6. Алгоритм Форда — Фалкерсона 52 1.2.7 Алгоритмы Диница и Карзанова..................................52 1.2.8. Изображение графов и сетей...................................56 Библиографический комментарий..........................................57 Список литературы......................................................58 Глава 2. Ориентированные деревья.......................................61 2.1. Ордеревья и их свойства...........................................61 2.1.1. Корневые деревья............................................ 61 2.1.2. Бинарные деревья.............................................66 2 1.3. Представление деревьев....................................67 2.1.4. Перечисление и подсчет деревьев . ................87 2.2. Обходы графов и деревьев в глубину и ширину.......................94 2.2.1. Разметки, нумерации, обходы, укладки.........................95 2.2.2. Базисные нумерации...........................................96 2.2.3. Обходы в ширину и глубину..........................................98 2.2.4. Остовный лес обхода в глубину и глубинное остовное дерево....99 2.2.5. Рекурсивный алгоритм обхода графа в глубину.................100 2.2.6. Общий алгоритм обхода графа с запоминанием дуг............. 100 2.2.7 Общий алгоритм обхода графа с запоминанием его вершин........102 2.2.8. Алгоритм обхода графа в ширину с использованием внешней очереди.102 2.2.9. Алгоритм обхода графа в ширину с использованием внутренней очереди 104
4 Содержание 2.2.10. Алгоритм обхода графа в ширину без использования дополнительной памяти................................................105 2.2.11. Алгоритм обхода в ширину графа с циклическими списками дуг...107 2.2.12. Способы прохождения бинарных деревьев........................109 2.2.13. Алгоритм обхода бинарного дерева в глубину с внешним стеком...НО 2.2.14. Алгоритм обхода в глубину прошитого бинарного дерева.........111 2.2.15. Замечания....................................................112 2.2.16. Алгоритм обхода бинарного дерева в глубину без использования дополнительной памяти................................................113 2.2.17 Обход в глубину произвольных деревьев и лесов.................115 2.2.18. Алгоритм обхода графа в глубину без использования дополнительной памяти................................................115 2.2.19. Алгоритм прямой нумерации вершин графа.......................117 2.2.20. Алгоритм базисных нумераций графа............................118 2.2.21. Алгоритм обхода графа в глубину с двусторонним прохождением дуг графа............................................................119 2.2.22. Алгоритм обхода графа в глубину с двусторонним прохождением дуг и распределенной реализацией стека...................................121 2.2.23. Алгоритм обхода графа в глубину с двусторонним прохождением дуг и без использования дополнительной памяти............................122 2.2.24. Алгоритм обхода в глубину графа, представленного в виде массива дуг, с двусторонним прохождением дуг графа................................125 2.3. Генерация деревьев.................................................126 2.3.1. Алгоритм генерации упорядоченных деревьев.....................126 2.3.2. Алгоритм генерации бинарных деревьев...........................129 2.3.3. Алгоритм генерации бинарных деревьев заданной высоты..........131 2.3.4. Алгоритм генерации А-арных деревьев...........................134 2.3.5. Алгоритм генерации корневых деревьев..........................135 2.3.6. Алгоритм генерации свободных деревьев.........................136 2.3.7. Генерация равновероятных Деревьев.............................139 2.3.8. Алгоритм прямой генерации равновероятных упорядоченных корневых деревьев...................................................140 2.3.9. Алгоритм генерации по номеру равновероятных А-арных деревьев..142 2.4. Каркасы............................................................144 2.4.1. Задача об отыскании оптимального каркаса......................144 2.4.2. Алгоритмы перечисления всех каркасов..........................160 2.4.3. Поиск каркасов с заданными свойствами.........................171 Библиографический комментарий...........................................175 Список литературы.......................................................179 Глава 3. Бесконтурные графы.............................................187 3.1. Основные свойства и алгоритмы......................................187 3.1.1. Основные свойства и подклассы.................................187 3.1.2. Топологическая сортировка.....................................193 3.1.3. Кратчайшие пути...............................................196 3.1.4. Критический путь..............................................196 3.1.5. Путевое покрытие..............................................197
Содержание 5 3.2. Транзитивное замыкание и транзитивная редукция.....................198 3.2.1. Необходимые определения.......................................198 3.2.2. Алгоритм Уоршалла.............................................200 3.2.3. Общая форма алгоритма Уоршалла................................200 3.2.4. Алгоритмы Горальчиковой-Коубека и Симона......................202 3.2.5. Алгоритм Жомард-Мину..........................................205 3.2.6. Быстрый алгоритм слияния списков..............................206 3.2.7 Определение транзитивного замыкания и транзитивной редукции при неполностью известной матрице смежности.........................208 3.2.8. Замыкание относительно множества вершин.......................210 3.3. Конгруэнтное замыкание отношения эквивалентности...................211 3.3.1. Задача нахождения конгруэнтного замыкания.....................211 3.3.2. Быстрый алгоритм конгруэнтного замыкания......................213 3.3.3. Ациклическое конгруэнтное замыкание...........................216 3.3.4. Уточнение алгоритма быстрого конгруэнтного замыкания..........219 3.3.5. Случай единственной эквивалентности...........................222 3.3.6. Симметричное конгруэнтное замыкание.......................... 223 3.3.7 Унификация.....................................................224 3.3.8. Проверка эквивалентности выражений............................224 3.3.9. Проверка свойства соединения без потерь.......................225 3.4. Нахождение ближайших предков.......................................227 3.4.1. Постановка проблемы...........................................227 3.4.2. Общий вид быстрого алгоритма для статических деревьев.........228 3.4.3. Сжатое дерево.................................................230 3.4.4. Сбалансированное бинарное дерево..............................235 3.4.5. Быстрый алгоритм для задачи с соединением корней..............238 3.4.6. Более быстрый алгоритм для задачи с соединением корней........241 3.4.7 Заключительные замечания.......................................243 3.5. Граф Герца.........................................................243 3.5.1. Бикомпоненты и граф Герца.....................................243 3.5.2. Матричный алгоритм отыскания бикомпонент орграфа..............244 3.5.3. Алгоритм Тарьяна отыскания бикомпонент........................244 3.5.4. Пошаговая форма алгоритма Тарьяна.............................246 3.5.5. Алгоритм Фараджева............................................247 3.5.6. Алгоритм Касьянова............................................248 Библиографический комментарий...........................................252 Список литературы..................................................... 254 Глава 4. Сводимые и регуляризуемые графы................................258 4.1. Класс сводимых графов............................................ 258 4.1.1. Уграф, фрагменты и подфрагменты...............................258 4.1.2. Альты, гамаки и интервалы.....................................260 4.1.3. Отношения обязательного предшествования и обязательной преемственности......................................262 4.1.4. F-лучи, F-области и правильная нумерация......................262 4.1.5. Фактор-уграфы.................................................264 4.1.6. Интервальное представление уграфа.............................265 4.1.7 Интервально-сводимые уграфы....................................267 4.1.8. Регуляризуемые уграфы.........................................269 4.1.9. Аранжировка и аранжируемые графы..............................271
6 Содержание 4.1.10. Разборные у графы.................................................272 4.1.11. Алгоритм проверки сводимости графа................................273 4.1.12. Упрошенный вариант алгоритма .....................................276 4.1.13. Порядок втягивания вершин................................... 278 4.1.14. Преобразование несводимых графов..................................279 4.1.15. Преобразования расщепления........................................279 4.1.16. Стандартное преобразование...................................... 282 4.2. Разрушение контуров в сводимых графах...................................283 4.2.1. Постановка задачи..................................................283 4.2.2. Необходимые определения............................................284 4.2.3. Потоковая сеть для G............................................................................................ 285 4.2.4. Определение мощности минимального множества разрывающих дуг..........288 4.2.5. Нахождение минимального множества вершин, разрезающего циклы.289 4.2.6. Приближенный алгоритм нахождения множества разрывающих дуг.........291 4.2.7. Алгоритм Бергера — Шора............................................293 4.2.8. Алгоритм Шамира....................................................295 4.3. Анализ циклической структуры и циклически сводимые графы................297 4.3.1. Понятие цикла в уграфе.............................................298 4.3.2. Достоверные частотные отношения......................................298 4.3.3. Участки повторяемости..............................................299 4.3.4. Циклические участки графа..........................................301 4.3.5. Циклически сводимые графы..........................................304 4.3.6. Полные ^-последовательности........................................306 4.3.7 Связь со сводимыми графами.........................................308 4.3.8. Алгоритм Шпекенмейера для задачи FVS...............................310 4.4. Перечисление путей......................................................311 4.4.1. Сильные и слабые укладки...........................................311 4.4.2. Построение укладок............................................... 313 4.4.3. Постановка задачи перечисления.....................................314 4.4.4. Формальная постановка задачи.......................................315 4.4.5. Алгоритмы перечисления путей................................... 319 4.4.6. Алгоритм прямого потокового анализа................................322 Библиографический комментарий.............................................. 329 Список литературы............................................................331 Глава 5. Визуализация........................................................335 5.1. Задача и методы визуализации............................................335 5.1.1. Рисование графов на плоскости......................................336 5.1.2. Ортогональные изображения..........................................340 5.1.3. Использование физических аналогий..................................345 5.1.4. Трехмерные представления...........................................346 5.1.5. Изображение помеченных графов................................... 349 5.2. Планарные графы и их изображения.......... 351 5.2.1. Планарные графы и их свойства......................................352 5.2.2. Рисование деревьев.................................................357 5.2.3. Рисование последовательно-параллельных графов......................363 5.2.4. Рисование бесконтурных графов......................................366 5.2.5. Переход к планарному графу.........................................371
Содержание 7 5.2.6. Выпуклые представления..........................................374 5.2.7 Методы, основанные на канонических упорядочениях.................377 5.3. Поуровневое рисование ориентированных графов.......................379 5.3.1. Общая схема поуровневого подхода..............................380 5.3.2. Распределение вершин по уровням...............................384 5.3.3. Определение порядка вершин на уровне..........................388 5.3.4. Определение координат вершин на уровне........................394 5.3.5. Предварительные преобразования графа..........................396 5.4. Иерархические графы и графовые модели..............................398 5.4.1. Иерархические графы...........................................399 5.4.2. Изображения иерархических графов............................ 403 5.4.3. Иерархические графовые модели.................................407 5.4.4. Использование инвариантных свойств для задания семантики модели.408 5.4.5. Трансформационный подход к заданию семантики графовой модели .410 5.5. Системы визуализации графов и графовых моделей..................412 5.5.1. Вопросы визуализации и визуальной обработки.................412 5.5.2. Системы визуализации и графовые редакторы.....................415 5.5.3. Графовые библиотеки...........................................430 5.5.4. Система HIGRES................................................436 Библиографический комментарий...........................................440 Список литературы................................. .......................442 ЧАСТЬ II. ПРИМЕНЕНИЕ ГРАФОВ И ГРАФ-МОДЕЛЕЙ..............................449 Глава 6. Информационные деревья.........................................451 6.1. Одномерные структуры данных........................................452 6.1.1. Деревья сортировки............................................452 6.1.2. ЛДД-деревья...................................................454 6.1.3. Балансированные по весу деревья (БД-деревья)..................455 6.1.4. Выровненные деревья...........................................459 6.1.5. 1-2-братские деревья..........................................461 6.1.6. 2-3-деревья...................................................468 6.1.7 Кучи...........................................................475 6.1.8. Д-деревья.....................................................481 6.1.9. Другие страничные деревья ....................................492 6.2. Многомерные структуры данных.......................................498 6.2.1. Многомерное дерево сортировки.................................498 6.2.2. Многомерные Д-деревья.........................................505 6.2.3. Деревья множественных атрибутов...............................515 6.2.4. Парадигмы для МАТ-структур....................................520 Библиографический комментарий......................................... 523 Список литературы..................................................... 525 Глава 7. Синтаксические деревья.........................................527 7.1. Синтаксис языка и задача фазы анализа..............................527 7.1.1. Синтаксис языка, лексемы, понятия и атрибуты..................527 7.1.2. Схема процесса трансляции.....................................532 7.1.3. Лексический, синтаксический и контекстный анализ..............533
8 Содержание 7.2. Порождающие грамматики...............................................535 7.2.1. Цепочки и языки ...............................................535 7.2.2. Грамматики составляющих........................................536 7.2.3 Контекстно-свободные языки.................................... 538 7.2.4. Эквивалентные преобразования грамматик.........................540 7.3. Лексический анализ................................................. 543 7.3.1. Распознаватели............................................... 543 7.3.2. Функции лексического анализа...................................546 7.3.3. Реализация лексического анализатора.......................... 548 7.4. Синтаксический анализ................................................549 7.4.1. Стратегии разбора..............................................549 7.4.2. Автоматы с магазинной памятью..................................550 7.4,3 Нисходящий ЛУ/7-распознаватель..................................553 7.4.4. /./.-грамматики и £/.-распознаватель...........................556 7.4.5 Восходящий Л//7-распознаватель.....................’............557 7.4.6. Грамматики предшествования.....................................559 7.4.7 Горизонтальный разбор...........................................561 7.4.8. Алгоритм Эрли................................................ 564 7.4.9. £Я-грамматики..................................................565 7.4.10. £Я-анализатор.................................................566 7.4.11. Обработка синтаксических ошибок...............................568 7.5. Перевод и конструкторы анализаторов..................................571 7.5.1. Понятие перевода, СУ-схемы и преобразователя...................571 7.5.2 Конструктор лексических анализаторов............................573 7.5.3. Конструкторы синтаксических анализаторов.......................575 7.5.4 Конструктор /./.-преобразователя................................576 7.5.5. Конструктор /.Я-преобразователя................................579 7.5.6. Использование конструкторов....................................581 Библиографический комментарий.............................................582 Список литературы.........................................................582 Глава 8. Контекстный анализ...............................................584 8.1. Задача контекстного анализа..........................................584 8.1.1. Атрибуты абстрактной программы.................................584 8.1.2. Области видимости и идентификация..............................586 8.1.3. Атрибутная индукция.......................................... 587 8.2. Атрибутные грамматики................................................590 8.2 1. Определение атрибутных грамматик...............................590 8.2.2. Пример атрибутной грамматики...................................592 8.2.3 Атрибутное вычисление...........................................593 8.3. Конструирование абстрактных синтаксических представлений.............597 8.3.1 Абстрактное синтаксическое дерево и построение дерева выражения.597 8.3.2. Дэги выражений.................................................600 8.3.3. Метод нумерации для конструирования вершин в дэге..............601 8.4. Основные подклассы атрибутных грамматик и вычислений.................603 8.4.1. Чисто синтезированные грамматики...............................603 8.4.2. /-упорядоченные грамматики.....................................605 8.4.3. Сильно ациклические грамматики.................................606
Содержание 9 8.4.4. Вычислители для грамматик общего вида.........................608 8.4.5. Восходящее вычисление для А-атрибутных грамматик..............609 8.5. £-атрибутные грамматики.............................................610 8.5.1. Порядок обхода в глубину и £-атрибутные грамматики............610 8.5.2. Трансляционные схемы..........................................611 8.5.3. Удаление левой рекурсии из трансляционной схемы...............612 8.5.4. Конструирование предсказывающего транслятора..................615 8.5.5. Удаление встроенных действий из трансляционных схем...........617 8.5.6. Наследуемые атрибуты на стеке разбора.........................618 8.5.7 Восходящий разбор и трансляция с синтезируемыми атрибутами.....620 8.5.8. Замена наследуемых атрибутов синтезированными.................621 8.5.9. Пример атрибутной грамматики, трудной для обработки...........622 8.5.10. Рекурсивные вычислители и обходы слева направо...............622 8.5.11. Другие обходы рекурсивных вычислителей.......................624 8.6. Распределение памяти под атрибуты...................................625 8.6.1. Вводные замечания.............................................626 8.6.2. Распределение памяти под атрибуты во время трансляции.........627 8.6.3. Удаление копирований..........................................629 8.6.4. Распределение памяти во время конструирования транслятора.....630 8.6.5. Пример генерации промежуточного представления............... 630 8.6.6. Неперекрывающиеся времена существования.......................632 Библиографический комментарий............................................634 Список литературы........................................................636 Глава 9. Кодогенерация...................................................640 9.1. Задача кодогенерации и объектная машина.............................640 9.1.1. Задача кодогенерации..........................................641 9.1.2. Вход кодогенератора...........................................643 9.1.3. Трехадресные представления....................................644 9.1.4. Объектные программы...........................................646 9.1.5. Управление памятью.......................................... 647 9.1.6. Выбор команд..................................................648 9.1.7 Распределение регистров........................................649 9.1.8. Выбор порядка вычисления......................................650 9.1.9. Архитектура объектной машины..................................650 9.1.10. Стоимость команды............................................652 9.2. Управление памятью периода исполнения...............................653 9.2.1. Вводные замечания.............................................653 9.2.2. Статическое распределение.....................................654 9.2.3. Стековое распределение........................................655 9.2.4. Адресация периода исполнения для имен.........................658 9.3. Линейные участки и управляющие графы................................659 9.3.1. Линейные участки и их выделение...............................659 9.3.2. Преобразования на линейных участках...........................662 9.3.3. Информация о последующем использовании........................663 9.3.4. Управляющие графы и представление лучей.......................665 9.4. Простой кодогенератор...............................................667 9.4.1. Вводные замечания.............................................667 9.4.2. Дескрипторы регистров и адресов...............................668
10 Содержание 9.4.3. Алгоритм кодогенерации........................................668 9.4.4 Функция нахождения места размещения............................669 9.4.5. Генерация кода для операторов других типов....................671 9.4.6. Условные операторы............................................672 9.5 Распределение и присваивание регистров..............................673 9.5.1. Глобальное распределение регистров............................673 9.5.2. Счетчики использований........................................674 9.5,3 Присваивание регистров для внешних циклов......................677 9.5.4. Распределение регистров путем раскраски графа.................677 9.6. Представление лучей дэгами и генерация кода по дэгу................678 9.6.1. Представление линейных участков в виде дэгов..................679 9.6.2. Конструирование дэга луча.....................................679 9.6.3. Применение дэгов..............................................682 9.6.4. Массивы, указатели и вызовы функций...........................684 9.6.5. Генерация кода по дэгу........................................686 9.6.6. Задача переупорядочения.......................................686 9.6 7 Эвристическое упорядочение для дэгов..........................687 9.6.8. Оптимальное упорядочение деревьев.............................689 9.6.9. Алгоритм разметки............................................ 689 9.6 10. Генерация кода по помеченному дереву........................691 9.6.11. Многорегистровые операции....................................693 9.6.12. Алгебраические свойства......................................694 9.6 13. Общие подвыражения..........................................695 9.7. Алгоритм кодогенерации, основанный на динамическом программировании........................................695 9.7.1. Класс регистровых машин.......................................696 9.7.2. Принцип динамического программирования и непрерывное вычисление............................................696 9.7.3. Непрерывное вычисление........................................697 9.7.4. Алгоритм динамического программирования.......................697 9.8. Покадровая оптимизация.............................................700 9 8.1. Понятие покадровой оптимизации...............................700 9.8.2. Избыточные загрузки и запоминания.............................701 9.8.3. Недостижимый код..............................................701 9.8.4. Оптимизации потока управления.................................702 9 8.5. Алгебраические упрощения.....................................703 9 8 6. Понижение силы операции......................................703 9.8.7. Использование машинных идиом..................................704 9.9. Генерация кодогенераторов..........................................704 9 9 1. Генерация кода и переписывание деревьев.......................704 9.9.2. Поиск по образцу при разборе..................................710 9.9.3. Процедуры семантической проверки..............................711 9.9 4. Покрывающие деревья ..........................................712 9 9.5. Система BEG...................................................713 9.10. Генерация оптимального кода для стековых машин....................715 9.10.1 Стековая машина и корневые деревья............................715 9.10.2. Стековые вычисления..........................................718 9.10.3. Коммутативные операции..................................... 720 9.10 4. Ассоциативные коммутативные операции.........................721
Содержание 11 Библиографический комментарий...............................~..........725 Список литературы.................................................... 728 Глава 10. Потоковый анализ программ....................................735 10.1. Анализ потока управления....................................... 736 10.1.1. Представление множеств исполнений..........................736 10.1.2. Структуризация........................................... 740 10.1.3. Нахождение свойств операторов и переходов..................741 10.1.4. Выбор порядка обработки операторов.........................742 10.2. Гамачное представление уграфов...................................747 10.2.1. Иерархия вложенных альтов..................................747 10.2.2. Нумерации К и L.......................................... 750 10.2.3. Алгоритм Л’-нумерации......................................751 10.2.4. Алгоритм /.-нумерации......................................752 10.2.5. Свойства нумераций К и L...................................753 10.2.6. Алгоритм выделения гамаков.................................754 10.3. Отношения обязательного предшествования и обязательной преемственности.........................................755 10.3.1 Отношение доминирования и их свойства.......................756 10.3.2. Семидоминаторы.............................................757 10.3.3. Алгоритм Ленгауэра — Тарьяна...............................759 10.3.4. Реализация операций LINK и EVAL............................763 10.3.5. Общий вид алгоритма Ленгауэра — Тарьяна....................765 10.3.6. Микродеревья и их использование........................ 767 10.3.7. Линейный алгоритм Бухбаума — Каплана — Роджерс.............769 10.3.8. Инкрементальное вычисление доминаторных деревьев............772 10.3.9. Алгоритм нахождения доминаторов в сводимом уграфе..........777 10.4. Структурная сложность программ....................................778 10.4.1. Понятие сложности программы................................778 10.4.2. Цикломатическая мера Мак-Кейба.............................779 10.4.3. Другие меры сложности, основанные на уграфе................782 10.4.4. Декомпозиция уграфов.......................................786 10.5. Потоковый анализ программ........................................791 10.5.1. Задача анализа потока данных...............................791 10.5.2. Метод разметки.............................................794 10.5.3. Примеры задач анализа свойств состояний.................. 796 10.5.4. Алгоритм нахождения стационарной разметки..................798 10.5.5. Факторизация.............................................. 801 10.5.6. Свойства схем анализа свойств состояний....................803 Библиографический комментарий..........................................812 Список литературы......................................................814 Глава 11. Преобразование программ......................................818 11.1. Унификация и системы переписывания термов........................818 11.1.1. Задача унификации..........................................819 11.1.2. Унификация как решение множества уравнений.................820 11.1.3. Мультиуравнения и алгоритмы их решения.....................822 11.1.4. Улучшение алгоритма унификации при обработке неунифицируемых данных............................................827
/2 Содержание 11.1.5. Алгоритм проверки унифицируемости, основанный на представлении термов дэгами.....................................829 11.1 6. Линейный алгоритм унификации Патерсона — Вегмана.......... 831 11.1.7. Алгоритм Уэ.................................................834 11.1.8. Сравнение алгоритмов унификации.............................836 1119. Эквациональные спецификации ............................. 838 11.1.10. Понятие системы переписывания термов.......................840 11.1.11. Свойство Черча — Россера, конфлюэнтность, нетеровость и полнота системы переписывания термов........................... 841 11 1.12. Локальная конфлюэнтность и критические пары . ........ 842 11.1.13. Построение полных СПТ для эквациональных теорий............844 11.1.14. Методы доказательства нетеровости, основанные на упорядочении.848 11.1.15. Алгоритм Кнута — Бендикса..................................850 11.2. Промежуточные представления программ..............................853 11.2.1. Требования к промежуточному представлению................. 853 112 2. Граф зависимостей по данным.............................. 855 11.2.3. Зависимость по управлению.................................. 857 11.2.4. Граф программных зависимостей...............................860 11.2.5. Построение графа зависимостей............................. 861 11.2.6. Иерархический граф заданий................................. 865 11.2.7 Построение ИГЗ...............................................867 1.1.3. Операторные модели программ......................................874 113 1. Семантические и формальные схемы программ....................874 11.3.2. Класс крупноблочных схем программ...........................875 11.3.3. Важные подклассы и их свойства..............................880 113 4. Перераспределение памяти............................. ..... 883 11.3.5. Схемы с распределенной памятью..............................885 11.3.6. Схематизация программ..................................... 891 11.3.7. Схемы с косвенной адресацией................................892 11.3.8. Корректные псевдораскраски................................. 896 11.3.9. Модель аннотированных программ..............................898 11.3.10. Преобразования программ....................................900 Библиографический комментарий ..........................................902 Список литературы..................................................... 907 Глава 12. Прочие граф-модели............................................914 12.1. Диаграммы бинарных решений........................................914 12.1.1. Упорядоченные диаграммы бинарных решений и логические фрагменты............................................ 915 12.1.2. Конструирование и манипуляция.............................. 922 12.1.3. Представление математических объектов.......................929 12.1.4. Другие применения.................................-.........933 12.2. Частично упорядоченные множества..................................943 12.2.1. Основные определения...................................... 943 12.2.2. Параметры чу-множеств.......................................946 12.2.3. Частично упорядоченные множества и графы................... 947 12.2.4. Решетки, подрешетки и полурешетки...........................949 12.2.5. Теорема о неподвижной точке.................................956
Содержание 13 12.2.6. Кодирование частичных порядков..............................957 12.2.7. Прозрачные частичные порядки и их применения................962 12.2.8. Чу-множества и модели параллельных программ и процессов.....969 12.3. Сети Петри.........................................................971 12.3.1. События и условия...........................................972 12.3.2. Определение сети Петри.................................... 973 12.3.3. Основные свойства сетей Петри...............................978 12.3.4. Ограниченность и безопасность сети........................ 979 12.3.5. Классы языков сетей Петри................................. 981 12.3.6. Подклассы сетей Петри.......................................985 12.3.7 Обобщения сетей Петри...................................... 988 12.3.8. Регулярные сети.............................................992 12.3.9. Иерархические сети..........................................995 12.4. Графы адресуемых данных............................................998 12.4.1. Граф данных.................................................998 12.4.2. Реализация графов данных...................................1003 12.4.3. Относительная адресация....................................1003 12.4.4. Вложения графов............................................1005 Библиографический комментарий...........................................1007 Список литературы.......................................................1009 ЧАСТЬ III. ПРИЛОЖЕНИЯ...................................................1013 Приложение 1. РАМ, ВУ-язык и список TVP-полных задач.......1015 1.1 РАМ и понятие АР-полноты............................................1016 1.1.1. Равнодоступная адресная машина...............................1017 1.1.2. Вычислительная сложность РАМ-программ........................1019 1.1.3. Свойства РАМ, связь РАМ с другими моделями вычислений........1020 Г. 1.4. Труднорешаемые и АР-полные задачи...........................1021 1.2. Язык высокого уровня...............................................1023 1.2.1. Структуры данных.............................................1024 1.2.2. Структуры действий...........................................1027 1.2.3. Дополнительные средства......................................1030 1.3. Список АР-полных задач.............................................1030 1.3.1. Покрытия и разбиения.........................................1030 1.3.2. Подграфы и изоморфизм........................................1032 1.3.3. Расположения, укладки и нумерации............................1036 1.3.4. Остовные деревья.............................................1038 1.3 5. Разрезы и связность...................................... 1041 1.3.6. Пути.........................................................1042 1.3.7 Сети..........................................................1044 1.3.8. Множества и разбиения........................................1046 1.3.9. Хранение и поиск.............................................1049 1.3.10. Программы и схемы ..........................................1053 1.3.11. Автоматы и языки............................................1056 1.3.12. Логика......................................................1058 1.3.13. Игры и головоломки..........................................1059 1.3.14. Алгебра и теория чисел......................................1062
14 Содержание 1.3.15. Математическое программирование...........................1064 1.3.16. Теория расписаний.........................................1066 13 17 Разные задачи ............................................1069 Библиографический комментарий....................................... 1070 Список литературы....................................................1072 Приложение 2. Характеристики размещений графов.......................1074 2.1. Размер области размещения.......................................1074 2.1.1 Деревья.....................................................1075 2.1.2. Планарные графы.......................................... 1076 2.1 3 Графы общего вида ..........................................1077 2.2. Оценка величины углов...........................................1077 2.3. Число сгибов....................................................1077 2.4. Связь разных характеристик......................................1078 2 4.1. Связь между размером и отношением сторон при изображении деревьев......................................1078 2.4.2. Связь между размером области и величины углового разрешения для планарных графов..........................................1079 2.5. Вычислительная сложность........................................1079 2.5.1. Проверка планарности и вложения............................1079 2.5.2. Прямолинейные и полилинейные изображения планарных графов..1080 2.5.3. Изображения графов с заданной степенью вершин..............1080 2 5.4. Рисование деревьев.........................................1081 Библиографический комментарий........................................1082 Список литературы....................................................1082 Предметный указатель.................................................1087
Введение Современное состояние программирования нельзя представить себе без теоретико- графовых алгоритмов. Хорошо известно, что многие задачи повышения качества трансляции, как в смысле улучшения рабочих характеристик транслятора, так и в смысле повышения качества получаемых машинных программ, формулируются и решаются как задачи на графах. Сюда относятся в первую очередь задачи, связанные с представлением программ в виде теоретико-графовых моделей, важнейшей из ко- торых является управляющий граф. Кроме того, необходимо указать на такие облас- ти применения граф-моделей, как эффективное использование ресурсов вычисли- тельной системы (оптимизация использования памяти, регистров, уменьшение обменов между оперативной и внешней памятью и т. д.), организация больших массивов ин- формации (деревья и, вообще, графы данных для повышения эффективности инфор- мационного поиска), увеличение степени параллелизма программы, повышение эф- фективности работы многопроцессорных и многомашинных систем (распределение загрузки процессоров, обмен сообщениями между процессами, синхронизация, кон- фигурация сетей связи между процессорами и т. д.). Решение этих и подобных задач привело к появлению множества граф-моделей, связанных как с программами и структурами данных, так и с вычислительными системами, в том числе параллель- ными. Разнообразное применение графов связано с тем, что они являются очень естествен- ным средством объяснения сложных ситуаций на интуитивном уровне. Эти преиму- щества представления сложных структур и процессов графами становятся еще более ощутимыми при наличии хороших средств их визуализации. Поэтому неслучайно в последнее время в мире растет интерес к методам и системам визуальной обработки графов и графовых моделей. Многие программные системы, особенно те, которые используют информационные модели, включают элементы визуальной обработки графовых объектов. Среди них — системы и окружения программирования, системы принятия решения, системы автоматизации проектирования и многие другие. Теория графов из академической дисциплины все более превращается в средство, владение которым становится решающим для успешного применения компьютеров во многих прикладных областях. Несмотря на наличие обширной специальной лите- ратуры по решению задач на графах, широкое применение в практике программиро- вания полученных математических результатов затруднено в силу отсутствия систе- матического их описания, ориентированного на программистов. Поэтому значитель- ный класс практических задач, по существу сводящихся к простому выбору подходящего способа решения и к построению конкретных формулировок абстракт- ных алгоритмов, для многих программистов все еще остается полем для интеллекту- альной деятельности по "переоткрытию" методов. Даже известный фундаментальный труд Д. Кнута "Искусство программирования для ЭВМ", если бы он и продолжился, как планировалось, не сможет решить эту проблему в силу ориентации Д. Кнута на низкоуровневое (в терминах машины MIX) описание алгоритмов. В изданных же
16 Введение трех томах серии излагается достаточно узкий класс используемых в программиро- вании граф-моделей (фактически Д. Кнут ограничился рассмотрением деревьев и уже не планирует продолжать работу над серией). Предлагаемая вниманию читателя книга является одной из первых попыток система- тизации знаний по алгоритмам теории графов для программиста. В отличие от Д. Кнута мы ориентируемся на абстрактную модель современных ЭВМ (равнодоступная адресная машина— РАМ) и высокоуровневое описание алгорит- мов в терминах специального языка высокого уровня — ВУ-язык. Этот язык является псевдоязыком (лексиконом) программирования и содержит в качестве базовых тра- диционные конструкции математики и языков программирования. Наряду с обычны- ми для современных языков типами простых и составных данных он допускает такие более сложные структуры данных, как, например, деревья, графы и т. д. Для каждой базовой конструкции ВУ-языка фиксируется класс ее допустимых реализаций на РАМ. Предполагается, что ВУ-язык позволяет наряду с базовыми использовать лю- бые необходимые конструкции, если очевидны или заранее зафиксированы оценки их сложности, а также те реализации этих конструкций на РАМ, которые допускают такие оценки. Такой подход позволяет формулировать алгоритмы в естественной форме, допускающей прямой анализ их корректности и сложности, а также простой перенос алгоритмов на традиционные языки программирования и ЭВМ с сохранени- ем полученных оценок сложности. Кроме того, подобный стиль описания алгоритмов является базой для доказательного стиля программирования: он позволяет понять алгоритм на содержательном уровне, оценить пригодность его для решения конкрет- ной задачи и осуществить модификацию алгоритма, не снижая степень математиче- ской достоверности окончательного варианта программы. Первая книга по теории графов появилась в 1935 году, однако началом широкого внедрения методов теории графов в практику научных и технических исследований следует считать 50-е годы XX века. В те годы были опубликованы отчеты американ- ской корпорации RAND по математическим исследованиям в военной области, кото- рые проводились в США во время и по окончании Второй мировой войны. Книги по теории графов (К. Берж, Р Басакер и Т Саати), вышедшие в начале 60-х годов, уже содержали материалы, относящиеся к приложениям теории графов в исследовании операций, дискретной оптимизации, электротехнике и пр. Затем последовали книги, посвященные алгоритмическим проблемам теории графов и вопросам применения теории графов в отдельных областях знаний, в том числе в программировании. Среди них нужно назвать: "Введение в теоретическое программирование. Беседы о методе" А. П. Ершова (1977 г.), "Применение теории графов в программировании" В. А. Евстиг- неева (1985 г.), "Оптимизирующие преобразования программ" В. Н. Касьянова (1988 г.), "Комбинаторика для программистов" В. Липского (1988 г.). Заметим, что любая из книг, содержащих теоретико-графовые алгоритмы, оставалась либо книгой по теории графов, либо книгой по основной предметной области, ис- пользующей теоретико-графовые методы. Развивая эту тематику, мы решили объ- единить в одной книге графовые алгоритмы решения для графовых задач и задачи по программированию вместе со специфическими алгоритмами их решения, основан- ными или использующими теоретико-графовые методы и алгоритмы. Этот подход подсказал нам идею разбить все множество графов, которые наиболее часто встре- чаются в практике решения задач программирования, на классы, объединив вокруг каждого такого класса соответствующие задачи из информатики и программирова-
Введение 17 ния. Такими классами выступили классы деревьев, бесконтурных (или ациклических) графов и сводимых (или регуляризуемых) графов. Заметим, что последние два класса относятся к ориентированным графам, а из класса деревьев используется подкласс корневых деревьев, что также относится к ориентированным графам. Данный подход был успешно реализован нами в книгах: "Теория графов: алгоритмы обработки де- ревьев” (1994 г.), "Теория графов: алгоритмы обработки бесконтурных графов" (1998 г.), "Сводимые графы и граф-модели в программировании" (1999 г.) и "Толко- вый словарь по теории графов в информатике и программировании" (1999 г.). Однако небольшой тираж этих книг сделал их недоступными студентам и специалистам по програм м ированию. Предлагаемая книга объединяет и существенно расширяет материал перечисленных книг, что позволит более эффективно использовать предлагаемые методы и алгорит- мы. Впервые в отечественной литературе в ней дается монографическое изложение материала по вопросам рисования графов и визуальной обработки графовых мо- делей. Книга состоит из 12-ти глав и 2-х приложений, образующих три части. Часть I посвящена обработке и визуализации графов. Основная задача этой части, состоящей из пяти глав, — описать базовые модели и алгоритмы, связанные с при- менением теории графов в программировании, включая вопросы визуализации и ри- сования графов. Изложение материала привязано к трем основным типам графов: деревья, дэги или бесконтурные графы и сводимые или регуляризуемые графы. От- дельно рассматриваются основные теоретико-графовые понятия и методы рисования и визуальной обработки графовых моделей. В части II, состоящей из семи глав, сосредоточен основной материал по применению графов и граф-моделей в программировании и информатике. В ней подробно рас- смотрены использования графовых моделей в таких основных областях приложения, как хранение и поиск информации, трансляция и оптимизация программ, анализ, преобразование и распараллеливание программ, параллельная и распределенная об- работка информации. Часть III содержит справочный материал и состоит из двух приложений. Приложе- ние I посвящено "переборным" (ЛТ-полным) задачам, в котором, наряду с введением понятия ТуР-полноты и рассмотрением списков АР-полных задач из различных об- ластей программирования и информатики, описываются РАМ и ВУ-язык, используе- мые в книге для представления и анализа алгоритмов. В приложении 2 приведены характеристики размещений графов, включая размер области размещения, оценки величины углов, число сгибов и пр. Формулировки основных свойств получают буквенные обозначения (А, Б, В, Г и т. д.) внутри каждого раздела, и ссылка на свойство в тексте образуется из номера раздела и его буквенного обозначения, например, свойство 1.2.3, А указывает на свойство А из раздела 1.2.3. Если производится ссылка на свойство в том же разделе, то номер раздела может опускаться. Рисунки в книге выполнены авторами с использованием системы для работы с гра- фами HIGRES1 1 Качество рисунков соответствует предоставленному авторами. Ред.
18 Введение Читатель, желающий расширить свои знания по применению графов в программиро- вании, может использовать краткие обзоры и комментарии, завершающие главы и приложения книги и содержащие ссылки на основные и доступные работы с допол- нительным материалом по теории-графов и ее применении в программировании В основном тексте ссылки на литературу, как правило, отсутствуют. Списки литера- туры в конце глав и приложений ни в коей мере не претендуют на библиографиче- скую полноту; за редким исключением, они содержат только публикации, упоминае- мые в кратких обзорах и комментариях. Монография основывается на работах авторов в рамках проектов, которые выполня- лись в лаборатории конструирования и оптимизации программ Института систем информатики Сибирского отделения Российской академии наук (ИСИ СО РАН) и на кафедре программирования Новосибирского государственного университета (НГУ) при финансовой поддержке Российского фонда фундаментальных исследований (РФФИ) и Минобразования. Авторы благодарны всем коллегам, принимавшим уча- стие в выполнении этих проектов, в первую очередь И. А. Лисицыну. Е. С. Мер- дишевой, Т. С. Мердишевой, В. Е. Казанцеву, Д. Е. Бабурину и И. Л. Мирзуитовой. Нельзя не назвать и тех, кто своими работами, советами и поддержкой способство- вал появлению этой книги. Прежде всего — это А. П. Ершов, С. С. Лавров, А. А. Летичевский, Э. 3. Любимский, В. Е. Котов, В. К. Попков и А. А. Берс. Всем им, а также И. П. Мелинг и Л. К. Грушецкой, оказавшим большую помощь в техни- ческой подготовке рукописи, авторы выражают искреннюю признательность. Наконец, авторы благодарят своих жен (Светлану Николаевну и Людмилу Анатоль- евну) и детей (Елену Викторовну, Александра Владимировича и Надежду Владими- ровну) за любовь и поддержку при работе над книгой (Светлана Николаевна также помогла нам с подготовкой большинства иллюстраций). Любовь, терпение и под- держка наших близких сделали эту книгу возможной, им она и посвящается. Книга такого объема не может не содержать ошибки. Мы будем благодарны за лю- бые замечания и пожелания. Присылайте их нам по адресу ИСИ СО РАН, Новоси- бирск, 630090. Можно также получить список известных опечаток и сообщить о най- денных ошибках по электронной почте и на страницах Web-сайта лаборатории кон- струирования и оптимизации программ ИСИ СО РАН. Чтобы получить инструкции, по адресу graphs@pco.iis.nsk.su отправьте письмо, содержащее слово Help в качест- ве темы письма. Извините, если мы не сможем лично ответить на все письма. Книга предназначена для широкого круга специалистов, использующих методы тео- рии графов при решении своих задач, в первую очередь для системных и прикладных программистов, а также для специалистов по системам автоматизации проектирова- ния (САПР), конструкторов сверхбольших интегральных схем (СБИС) и т. д. Она может быть использована в качестве учебного пособия студентами высших учебных заведений, аспирантами и преподавателями, читающими соответствующие курсы. В принципе книга самодостаточна, т. е. содержит весь необходимый материал, все же желательно предварительное знакомство с основами теории графов и программиро- вания.
ЧАСТЬ I Обработка и визуализация графов Глава 1. Графы и сети Глава 2. Ориентированные деревья Глава 3. Бесконтурные графы Глава 4. Сводимые и регуляризуемые графы Глава 5. Визуализация
Основная задача данной части, состоящей из пяти глав, — описать базовые модели и алгоритмы, связанные с применением теории графов в программи- ровании, включая вопросы визуализации и рисования графов. Особое вни- мание в ней уделяется трем основным для программирования типам графов: деревьям, дэгам и регуляризуемым графам. Глава 1 содержит основные определения, относящиеся как к неориентиро- ванным, так и ориентированным графам, а также важные для последующих глав сведения о свойствах графов, некоторых классах графов и алгоритмов. Глава 2 посвящена ориентированным деревьям. Алгоритмы на деревьях об- разуют один из наиболее важных и широко используемых в программирова- нии классов алгоритмов теории графов. Эти алгоритмы по своей фундамен- тальности для задач обработки информации можно сравнить только с алго- ритмами вычисления функций анализа или алгоритмами линейной алгебры в вычислительной математике. Основное содержание главы — обходы гра- фов и деревьев и генерация деревьев. Завершается глава рассмотрением кар- касов графа. Глава 3 посвящена другому основному классу графов — бесконтурным гра- фам, или дэгам. Помимо основных определений и свойств дэгов приводятся методы и алгоритмы построения транзитивных и конгруэнтных замыканий, нахождения общих предков двух вершин дерева, выявления бикомпонент и построения графов конденсации (графов Герца). В главе 4 рассматривается последний из основных типов графов — сводимые или регуляризуемые Регуляризуемые графы представляют собой наиболее общий тип граф-моделей структурированных программ. Они поддерживают эффективное проведение оптимизирующих и распараллеливающих преобра- зований программ и являются основой трансформационного подхода к кон- струированию надежного и эффективного программного обеспечения. Кро- ме описания основных свойств регуляризуемых графов, рассмотрены такие важные задачи, как задача разрушения контуров, анализ циклической струк- туры графа и перечисление путей. Глава 5 посвящена новому направлению в прикладной теории графов — ви- зуализации и изображению графов на плоскости. Визуализация графов и графовых моделей является ключевым компонентом многих приложений в науке и технике. Глава включает следующие разделы: задача и методы ви- зуализации, планарные графы и их изображение, поуровневое рисование орграфов, иерархические графы и граф-модели, системы визуализации гра- фов и графовых моделей.
ГЛАВА 1 Графы и сети В данной главе вводятся основные понятия теории графов без особых подробностей, т. к. с этим материалом можно ознакомиться в любой из известных монографий по теории графов, комбинаторике или дискретной математике. Обсуждается ряд фунда- ментальных проблем теории графов; некоторые из них подробно рассматриваются в этой книге 1.1. Неориентированные графы Понятие неориентированного графа является основным в теории графов, в частности в так называемой математической теории графов. 1.1.1. Обыкновенные графы и их свойства Существуют несколько определений графа. Рассмотрим три из них. 1. Графом называется пара (И, £), где V — непустое множество объектов некоторой природы, называемых вершинами графа, а Е— подмножество двухэлементных подмножеств множества V, называемых ребрами графа. Множества вершин и ре- бер графа G обозначают Р(С) и E(G), соответственно. Если |P(G)| = п и |E(G)| = т, то говорят о (л, /и)-графе G. 2. Графом называется пара (Р, Е), где V— множество вершин графа, а Е— множе- ство ребер— есть подмножество множества И2 /~ классов эквивалентности, на которые множество К2 = {(v, w), v*w] разбивается следующим отношением эквивалентности: (V,, W|) ~(V2, W2) <=> (Vb W|) = (v2, w2) или (vb w,) = (w2, v2). 3. Графом называется тройка (V, E, P), где V— множество вершин, Е— множество объектов некоторой природы, отличной от природы вершин, называемых ребра- ми, Р— инцидентор, сопоставляющий каждому ребру е е Е пару граничных вер- шин v и w из V
22 Часть I. Обработка и визуализация графов Вершины и ребра графа называются также элементами графа, число вершин в гра- фе — порядком, а число ребер — размером графа. Граф называется конечным, если число ребер в нем конечно, и бесконечным — в противном случае. Для ребра е = (v, w) вершины v, w g K(G) называются концевыми (граничными) вер- шинами ребра е. Две концевые вершины одного и того же ребра называются смеж- ными. Два ребра называются смежными, если они имеют общую концевую вершину Ребро е называется кратным, если существует, по крайней мере, еще одно ребро е' с теми же концевыми вершинами. Ребро вида (v, v) называется петлей. Граф без петель и кратных ребер называется простым или обыкновенным графом. Граф с кратными ребрами называется мулыпиграфом. Граф, допускающий петли (и кратные ребра), называется псевдографом. Заметим, что первое из трех определений графа допускает петли, но не допускает кратные ребра, когда как третье допускает и петли, и кратные ребра. Основные свойства графов К основным свойствам графов относятся следующие (все определения и обоснования будут изложены ниже в данном разделе): П связность, в том числе реберная и вершинная связности, а также 1- и 2-связность; П планарность, а также укладка графа на заданной поверхности; П эйлеровость и гамильтоновость графов; □ раскрашиваемость и распознаваемость. Рассмотрим эти свойства подробнее. Связность графов Пусть V|, v2,..., ..., v*— последовательность вершин такая, что каждая пара соседних вершин v„ vj+| определяет ребро в графе. Тогда данная последовательность называется маршрутом. Маршрут называется простым или цепью, если ни одна вершина не встречается в нем дважды. Вершины v( и vk называются концевыми вер- шинами цепи. Граф называется связным, если каждая пара вершин в графе соединена цепью (рис. 1.1). Связность есть бинарное отношение на множестве вершин графа, обладающее свой- ствами рефлексивности, симметричности и транзитивности, т. е. связность есть от- ношение эквивалентности. Класс эквивалентности называется компонентой связно- сти. Ясно, что граф G является связным, если он содержит только одну компоненту связности. В противном случае граф называется несвязным. Несвязный граф с п вершинами, каждая компонента связности которого состоит из одной вершины, называется пустым графом и обозначается О„. Пустой граф не со- держит ребер, но может содержать произвольное число вершин. Альтернативой ему служит полный граф, в котором каждая пара вершин соединена ребром. Полный граф на п вершинах обозначается К„.
Гпава 1. Гоафы и сети 23 A(G) = 0 1110 10 110 110 10 10 10 1 0 0 0 1 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 1 0 10 10 0 110 0 0 0 0 0 0 0 0 0 1 1 0 0 0 0 1 0 0 0 1 0 0 110 0 0 110 0 10 10 0 110 0 0 0 0 0 0 1 0 0 0 1 0 е) Рис. 1.1. Неориентированный граф: а — связный, б— несвязный, е — матрица смежности Граф называется двудольным, если существует такое разбиение множества его вер- шин на две части (доли), что концевые вершины каждого ребра принадлежат разным частям. Если при этом любые две вершины, входящие в разные доли смежны, то граф называется полным двудольным. Часто нужно уточнить понятие связности, указав, удаление какого элемента графа приводит к потере связности. Вершинная и реберная связности Граф G называется к-вершинно связным, если в нем найдется множество из к вершин, удаление которых делает граф несвязным, и никакое множество из меньшего количе- ства вершин не обладает этим свойством. Число к называется числом вершинной связности. Указанное множество вершин еще называется сепаратором. Граф называется 1-вершинно связным, если в нем найдется такая вершинах, удаление которой делает граф несвязным. Такая вершина называется точкой сочленения или
24 Часть I. Обработка и визуализация графов шарниром. Поскольку при изучении связности в основном речь идет о вершинной связности, слово "вершинная" опускается. Аналогично определяется 2-связность. Граф без точек сочленения называется блоком. Связность блоков не ниже двух, по- этому блоки еще называются компонентами двусвязности. Процедура разбиения графа на блоки отличается от обычного разбиения графа на компоненты связности тем, что удаление точки сочленения состоит в замене ее на столько копий, сколько блоков ее содержит, и каждая копия включается в соответствующий блок (рис. 1.2). Рис. 1.2. Блоки и точки сочленения: а — граф с точками сочленения, б — блоки, в — Ьс-граф Граф, состоящий из некоторого количества блоков, имеет деревообразную структуру (дерево Хусими), что особенно наглядно выглядит, если использовать для ее пред- ставления специальное дерево, называемое блочно-шарнирным деревом. Под послед- ним понимается дерево с множеством вершин двух типов: вершины xh изображаю- щие блоки, и вершины yz, изображающие точки сочленения (шарниры). Ребра дерева имеют вид (х„уу) и связывают блоки с соответствующими точками сочленения. Для иллюстрации структуры графов, содержащих точки сочленения, используются так называемые графы блоков и графы блоков и точек сочленения. Под первым по-
Гпава 1. Графы и сети 25 нимается граф B(G), вершинами которого являются блоки графа G, и две вершины смежны тогда и только тогда, когда соответствующие им блоки имеют общую точку сочленения. Под вторым понимается двудольный граф bc(G), вершинами которого служат блоки В, и точки сочленения с;, причем две вершины смежны, если одна представляет блок В„ а другая — точку сочленения с7, принадлежащую этому блоку. То есть оба графа являются деревьями. Ребро, концевые вершины которого являются точками сочленения, называется мос- том. Мост представляет собой вырожденный блок. Существует граф, каждое ребро которого является мостом или висячим ребром. Этот граф есть не что иное, как де- рево. А. Пусть aub — две вершины. Для существования сепаратора мощности к, разде- ляющего указанные вершины а и Ь, необходимо и достаточно существование к вер- шинно-различных, т. е. не имеющих общих вершин, отличных от а и b, (a, Ь)-цепей. Граф G называется h-реберно связным, если в нем найдется множество из h ребер, удаление которых делает граф G несвязным, и никакое множество из меньшего числа ребер этим свойством не обладает. Число h называется числом реберной связности. Назовем степенью вершины v число ребер, для которых v служит концевой верши- ной. Степень вершины v обозначается deg v. Степени вершин, упорядоченные по убыванию, образуют степенную последовательность. Наибольший элемент этой последовательности называется степенью графа и обозначается A(G'), последний элемент степенной последовательности не имеет специального названия, но имеет специальное обозначение 8 Справедливо следующее свойство графов. Б. Для трех заданных целых чисел р, q, г таких, что p<q<r, существует граф, та- кой, что k-p, h = q, Ъ = г Перечислим некоторые свойства степенной последовательности. В. у , ] deg v, = 2 m. Г. Число нечетных элементов степенной последовательности четно. Д. В степенной последовательности хотя бы два элемента имеют одну и ту же величину. Из свойства Д вытекает, что не существует конечного графа, у которого все степени различны. Используя понятие степени, можно ввести важный класс графов, а именно класс ре- гулярных графов, к которому относятся графы, вершины которых имеют одну и ту же степень (рис. 1 3). Если степени вершин равны к, то говорят о к-регулярных гра- фах. Так пустой граф является О-регулярным графом, полный п-вершинник — (л-1 (-регулярным графом. Назовем циклом цепь в графе, концы которой совпадают. Граф, представляющий со- бой цикл С„, есть 2-регулярный граф. К 3-регулярным графам относится, например, граф Петерсена.
26 Часть I. Обработка и визуализация графов Рис. 1.3. Регулярные графы: а — О-регулярный (пустой граф), б— 1-регулярный граф (Кг), в— 2-регулярный граф (цикл С5), г— 3-регулярный граф (граф Петерсена) Смежность Если (а, Ь) — ребро графа, то говорят, что вершины а и Ь смежны. Отношение смеж- ности задается матрицей смежности Л(С). Это квадратная матрица размером и * и (где п — порядок графа), у которой элемент ач равен 1, если вершины v, и у, смежны, и равен 0 в противном случае. Мы считаем отношение смежности нерефлексивным, поэтому полагаем ati = 0. Очевидно, что степень deg v вершины v — это число смежных с v вершин. Более того, сумма чисел в z-й строке матрицы смежности равна степени вершины v,. Множество смежных с v вершин называется окрестностью вершины v (обозначение N(v)). Замк- нутой окрестностью 7V[v] вершины v называется граф, порожденный вершинами W(v)u{v}. Два ребра называются смежными, если они имеют общую вершину. Граф L(G) назы- вается реберным графом для графа G, если каждому ребру в G ставится в соответст- вие вершина графа L(G), и две вершины считаются смежными, если смежны соответ- ствующие ребра. К важнейшим свойствам матрицы смежности относится тот факт, что матрица смеж- ности определяет граф с точностью до изоморфизма. Заметим кстати, что при ис- пользовании матрицы смежности в качестве структуры данных нельзя понизить тру- « 2 доемкость алгоритма до величины, меньшей п , т. к. только ввод матрицы смежности имеет такую трудоемкость. В силу того, что отношение смежности в неориентированных графах симметрично, т. е. fl,у = aJh следует симметричность матрицы смежности относительно главной диа- гонали. Поэтому, в принципе, достаточно задать верхнюю треугольную матрицу, чтобы иметь всю информацию о графе. Подграфы и частичные графы Для того чтобы работать с частями графа, требуется ряд определений. Пусть дан граф G = (V, Е). Частичным графом или частью графа называется граф И = (Х, U) такой, что Ус Г и U с Е, причем концы ребра е, входящего в U, обяза- тельно принадлежат X. Частичный граф И графа G может быть определен на всем множестве V, т. е. Н = (Г, СТ); в этом случае говорят о суграфе.
Гпава 1. Графы и сети 27 Подграфом L = (У, Z) заданного графа G = (У, Е) называется граф, который удовле- творяет следующим условиям: 1. Г с V;ZclE. 2. Если а, b е У и (a, b) е Е, то (a, b) е Z. Из этих определений вытекает, что в первом случае определяющим фактором являет- ся множество ребер, во втором — множество вершин. Поэтому можно говорить о подграфах, порожденных ребрами, и о подграфах, порожденных вершинами. Во втором случае также говорят об индуцированных подграфах. Если в графе G найдется подграф, изоморфный данному графу Н, то говорят об изо- морфном вложении графа Н в G. Если же в графе G найдется такой частичный граф L, у которого каждому ребру в Н сопоставляется простая цепь в L, то говорят о го- меоморфном вложении Н в G. Матрица инцидентности Если е = (а, Ь) — ребро в графе G, то можно говорить, что ребро е инцидентно вер- шине а или вершине аналогично определяем инцидентность вершин а, b ребру е. Отношение инцидентности представляется в виде матрицы B(G) инцидентности размером п х т, у которой элемент Ьк, равен 1, если вершина vk инцидентна ребру е„ и равен 0 в противном случае. В каждом столбце матрицы всего 2 единицы, равных столбцов нет. Матрица инцидентности также содержит всю информацию о графе, но ее использо- вание затруднительно из-за большого количества нулей. Двусвязные графы Случаи, когда к = 2 и к = 3, наиболее интересны в теории графов. Это объясняется несколькими причинами. Во-первых, 2- и 3-связные графы фигурируют во многих теоретических и прикладных задачах, в частности ряд задач достаточно уметь решать для двусвязных графов. Во-вторых, при к = 3 и, особенно, для к = 2 удается дать в некоторой степени обозримое описание соответствующих графов. Рассмотрим некоторые простые свойства 2-связных графов, вытекающие из опреде- ления. Ж. Степени вершин 2-связного графа больше единицы. 3. Если графы G} и G2 2-связны и имеют не менее двух общих вершин, то граф G\\J G2 также 2-связен. И. Если граф G 2-связен и Р — простая цепь, соединяющая две его вершины, то граф GkJ Р также 2-связен. К. Если вершина v не является точкой сочленения связного графа, то любые его вершины соединены цепью, не содержащей v; в частности, в 2-связном графе для любых трех несовпадающих вершин а, Ь, v имеется (а, Ь)-цепь, не проходящая че- рез V.
28 Часть I. Обработка и визуализация графов Л. Пусть G — связный граф, имеющий не менее 3 вершин. Тогда следующие утвер- ждения эквивалентны □ граф 2-связен\ □ любые две вершины графа принадлежат простому циклу, □ любая вершина и любое ребро принадлежат простому циклу, □ любые два ребра принадлежат простому циклу', □ для любых двух вершин а и Ь и любого ребра е существует простая (а, Ь)-цепъ, содержащая е; □ для любых трех вершин а, Ь, с существует простая (а, Ь)-цепь, проходящая через с. Если в формулировке свойства Л заменить всюду слова "простая цепь" и "простой цикл" соответственно на слова "цепь" и "цикл", то получим аналогичное свойство для реберно двусвязных графов. Планарность графов Плоским графом называется граф, вершины которого являются точками на плоско- сти, а ребра— непрерывными плоскими линиями без самопересечений, соединяю- щими соответствующие вершины так, что никакие два ребра не имеют общих точек, кроме инцидентной им обоим вершины (рис. 1.4). Рис. 1.4. Плоский граф Любой граф, изоморфный плоскому графу, носит название планарного графа. Очевидно следующее свойство планарного графа. 4. Всякий подграф планарного графа планарен, а граф планарен тогда и только то- гда, когда каждая его компонента связности — планарный граф. О планарных графах говорят, что они укладываются на плоскости или что они имеют плоскую укладку. Гранью плоского графа называется максимальное по включению множество точек плоскости, каждая пара которых может быть соединена жордановой кривой, не пере- секающей ребра графа. Тем самым утверждается, что каждая точка плоскости при- надлежит хотя бы одной грани плоского графа. Границей грани называется множест- во вершин и ребер, принадлежащих этой грани. Заметим, что всякий плоский граф
Гпава 1. Графы и сети 29 имеет одну, и только единственную, неограниченную грань. Такая грань называется внешней, а остальные — внутренними. Сформулируем некоторые свойства плоских графов. Н. Всякий планарный граф допускает такую плоскую укладку, в которой любая вы- бранная вершина (ребро) будет принадлежать внешней грани. О. Пусть граф G состоит из двух связных компонент G\ и G2, являющихся плоскими графами, и произвольным образом выбраны вершины V) е H(Gi) и v2 е C(G2). Тогда граф G, полученный слиянием вершин V| и v2 в вершину v, имеет плоскую укладку. При этом вершина v является точкой сочленения графа G. П. Всякие две вершины, принадлежащие границе некоторой грани плоского графа, можно соединить простой цепью произвольной длины так, что выбранная грань разобьется на две грани. Р. Для любого плоского графа каждая точка плоскости, не лежащая на ребре, вхо- дит только в одну грань, а каждая точка ребра, не являющаяся вершиной, входит только в одну грань, если это ребро является мостом, и точно в две грани, если оно — не мост. Пусть п, m,f— соответственно число вершин, ребер и граней плоского графа. Теорема Эйлера. Для всякого связного плоского графа верно равенство п — т + f = 2. Указанное равенство называется формулой Эйлера. С. Плоский граф двусвязен тогда и только тогда, когда границей всякой его грани является простой цикл. Критерии планарности Имеется несколько критериев планарности графов. Следует отметить, что практиче- ская проверка условий, которыми характеризуются планарные графы, не всегда явля- ется простой. Исторически первым критерием планарности является критерий Куратовского. Теорема Куратовского. Граф планарен тогда и только тогда, когда он не содер- жит частичных графов, гомеоморфных графам К5 и К33. Здесь К5 — полный 5-вершинник, а К33 — полный двудольный граф, известный под названием "три дома и три колодца". Оба эти графа носят название графов Куратов- ского. Теорема Вагнера (1936). Для любого планарного графа существует плоская укладка, в которой все ребра изображены в виде отрезков прямых линий. Теорема Вагнера (1937). Граф планарен тогда и только тогда, когда в нем нет под- графов, стягиваемых к графам К3 и К33. Теорема Маклейна. Граф планарен тогда и только тогда, когда в каждом его не- тривиальном блоке есть такой базис циклов С>, С2, С* и такой дополнительный цикл Со, что любое ребро блока принадлежит ровно двум из этих k + 1 циклов.
30 Часть I. Обработка и визуализация графов Обходы графа: эйлеровы графы Цикл в графе называется эйлеровым, если он содержит все ребра графа. Связный граф, в котором есть эйлеров цикл, называется эйлеровым. Такой граф можно нари- совать, не отрывая карандаша от бумаги и не повторяя линий. Т. Связный граф является эйлеровым тогда и только тогда, когда степени его вер- шин четные. У. Если связный граф содержит ровно к вершин нечетной степени, то минимальное число покрывающих его реберно-непересекающихся цепей равно к/2. Отсюда следует, что к должно быть четным. В частности, когда к = 2, граф имеет цепь, которая соединяет вершины с нечетными степенями и содержит все ребра графа. Цепь, содержащая все ребра графа, называет- ся эйлеровой. Граф, содержащий эйлерову цепь, так же называется эйлеровым Алгоритм Флёри Рассмотрим следующую задачу: найти хотя бы один эйлеров цикл в эйлеровом графе G, т. е. как занумеровать ребра графа числами 1,2,..., т (где т = |£|) с тем, чтобы номер, присвоенный ребру, указывал, каким по счету это ребро проходится в эйлеро- вом цикле. Это можно сделать, если нумеровать ребра, придерживаясь следующих двух правил: 1. Начиная с произвольной вершины и, присваиваем произвольному ребру (и, v) но- мер 1. Затем вычеркиваем ребро (и, v) и переходим в вершину v. 2. Пусть w— вершина, в которую мы пришли в результате выполнения предыдуще- го шага, и к— номер, присвоенный некоторому ребру на этом шаге. Выбираем другое ребро, инцидентное вершине w, причем мост мы выбираем только в том случае, когда нет других возможностей; присваиваем выбранному ребру номер к + 1 и вычеркиваем его. Этот процесс, называемый алгоритмом Флёри, заканчивается, когда все ребра графа вычеркнуты, т. е. занумерованы. Обходы графов: гамильтоновы графы Граф называется гамильтоновым, если в нем имеется простой цикл, содержащий все вершины этого графа. Сам этот цикл также называется гамильтоновым. Гамильто- новой называют и простую цепь, содержащую каждую вершину графа. Не все связные графы гамильтоновы хотя бы потому, что такой граф должен быть двусвязным. Однако одной двусвязуости недостаточно. Примером графа, двусвязно- го, но не гамильтонова, служит тэта-граф, имеющего две вершины, связанные тре- мя простыми цепями, образованными более чем двумя ребрами каждая. Несмотря на внешнее сходство постановок, задачи распознавания эйлеровости и ia- мильтоновости графа принципиально различны. Используя свойство 1.1 1,Т, легко узнать, является ли граф эйлеровым. В случае положительного ответа алгоритм Флё- ри позволяет достаточно быстро построить один из эйлеровых циклов.
Глава 1. Графы и сети 31 Ответить на вопрос, является ли данный граф гамильтоновым, как правило, очень трудно. Заметим, что проблема распознавания гамильтоновости графа есть частный случай проблемы изоморфного подграфа. Достаточные условия гамильтоновости Основная масса доказанных теорем утверждает, что при выполнении определенных условий граф содержит гамильтонов цикл, причем метод доказательства таких тео- рем обычно дает и эффективный алгоритм построения самого гамильтонова цикла. Интуитивно ясно, что если граф содержит много ребер и эти ребра достаточно рав- номерно распределены, то граф имеет много шансов быть гамильтоновым. Приведем три теоремы, подтверждающие это утверждение. Теорема Хватала. Граф со степенной последовательностью <7| < <У2 < ... < dn являет- ся гамильтоновым, если для всякого к, удовлетворяющего неравенствам 1 < к < «/2, истинна импликация (dk<k')^>(d„_lc>n —к). С помощью теоремы Хватала можно получить ряд других достаточных условий га- мильтоновости. Эти условия проще и, естественно, слабее условий, сформулирован- ных в теореме Хватала. Теорема Оре. Если для любой пары и и v несмежных вершин графа G порядка п>3 выполняется неравенство deg и + deg v > п, то G — гамильтонов граф. Теорема Дирака. Если |G| = п > 3 и для любой вершины v графа G выполняется не- равенство deg v >nfl, то G — гамильтонов граф. Нетрудно заметить, что во всяком «-вершинном графе, удовлетворяющем условиям любой из рассмотренных теорем, число ребер не меньше чем ((« —1)2)/4. С другой стороны, «-вершинный планарный граф, как это можно вывести из формулы Эйлера, содержит не более 3«— 6 ребер. Поэтому рассмотренные достаточные условия заве- домо неприменимы к планарным графам. Следующая теорема устанавливает связь гамильтоновости планарного графа с его связностью. Теорема Татта. Всякий 4-связный планарный граф является гамильтоновым. Следствием теоремы является следующее свойство. Ф. Если в максимальном плоском графе G каждый 3-цикл является границей неко- торой грани, то G — гамильтонов граф. 1.1.2. Деревья и их основные свойства Деревом называется неориентированный связный граф без циклов (рис. 1.5). Несвяз- ный неориентированный граф без циклов называется лесом. Другими словами, лес есть несвязный граф, каждая компонента связности которого есть дерево. Дерево с одной вершиной называется тривиальным, вырожденным или пустым.
32 Часть I. Обработка и визуализация графов Деревья обладают рядом свойств, каждое из которых полностью характеризует его. А. Следующие утверждения эквивалентны: П Т— дерево’, □ Т— неориентированный граф, любые две вершины которого связаны единствен- ной цепью’, □ Т— неориентированный граф без циклов, но добавление любого ребра к которому приводит к появлению в точности одного цикла’, П Т— связный неориентированный граф, у которого удаление любого ребра приво- дит к нарушению связности’, □ Т— связный п-вершинный неориентированный граф с п — 1 ребрами’, П Т— неориентированный граф без циклов с п вершинами и п- 1 ребрами’, П Т— неориентированный граф, все цепи которого простые, тп. е. ни одна вершина не входит в них дважды. Расстояние d(x,y) между вершинами х и у в дереве есть число ребер в цепи, соеди- няющей эти вершины. Расстояние от вершины х до наиболее удаленной от нее вер- шины называется эксцентриситетом е(х) вершины х, т. е. е(х) = max d(x,y) у Наименьший из эксцентриситетов называется радиусом г(Т) дерева Т’ r(T) = min е(х) = min max d(x,y) X X у Наибольший из эксцентриситетов называется диаметром D(T) дерева Т; D(T) = max max d(x, у) x у Вершина х называется центральной вершиной дерева, если для нее е(х) = г(Т), центр дерева— это множество его центральных вершин. Центр дерева состоит из одной
Гпава 1. Графы и сети 33 вершины или двух смежных вершин. Дерево, центр которого состоит из двух вер- шин, называется бицен тральным. Рассмотрим свойства дерева, связанные с центром. Б. Центр дерева не меняется, если у дерева удалить все висячие вершины. В. Радиус и диаметр дерева связаны соотношениями: диаметр D(T) равен 2/(7), если центр состоит из одной вершины, и 2г(Т) — 1, если центр состоит из двух вершин. Г. Каждая цепь наибольшей длины проходит через центр дерева. Каркасы Каркасом неориентированного графа называется его суграф в виде дерева (рис. 1.6). Каркас называется также остовом или стягивающим или остовным деревом. Неори- ентированный граф имеет каркас, если он связен. Элементарным преобразованием каркаса Т в каркас Т' называется добавление к Т ребра е (при этом образуется в точности один цикл) и удаление ребра е '(входящего в образовавшийся цикл), так что снова получается каркас. Для любых двух каркасов Т' и Т" всегда найдется последовательность (возможно пустая) каркасов 7), Т2,..., 7* такая, что каркас 77 получается из каркаса 7)_ । элементарным преобразованием. Пусть ребра графа как-то упорядочены. Тогда каждому каркасу ставится в соответст- вие вектор длины т, где т есть число ребер в графе, Z-я координата которого равна 1, если ребро <?, входит в данный каркас, и равна 0 — в противном случае. Этот вектор носит название вектор-каркаса. Относительно пространства вектор-каркасов извест- но следующее свойство. 2 Зак 202
34 Часть I. Обработка и визуализация графов Д. Размерность пространства вектор-каркасов равна числу ребер т исходного гра- фа, если он двусвязеи, и равна т — b(C) + I в противном случае', где b(G) — число блоков в графе. 1.1.3. Хордальные графы и их классификация Граф называется хордальным, если он не содержит индуцированных подграфов, изо- морфных циклу Ск для всех к > 4 (рис. 1.7). Другими словами, в хордальном графе любой цикл длины больше 3 имеет хорду (от- сюда и название). Так как любой простой цикл в хордальном графе — треугольник, то граф называется также триангулированным. а) б) Рис. 1.7. Хордальные графы а — хордальный граф, б— граф не являющийся хордальным (вершины a. b, с, d е f порождают цикл С6) Заметим, что свойство графа быть хордальным наследственное, т. е. если граф — хордальный, то таким же будет и каждый индуцированный его подграф. К настояще- му времени существует много способов характеризации хордальных графов, начиная с характеризации Г Дирака (1960) до совсем недавних. Рассмотрим характеризацию связных хордальных графов, принадлежащую Г. Дираку, в которой используется понятие разделяющего множества вершин. Мно- жество 5 вершин графа G называется разделяющим множеством вершин или сепа- ратором, если граф G \ S имеет больше компонент связности, чем граф G. Если при этом С„ 1 < i<l— компоненты графа G\S, образованного теми элементами графа G, которые не принадлежат S, то порожденные подграфы G(V(G) о S называются час- тями графа G относительно S. А. Связный граф является хордальным тогда и только тогда, когда любое его раз- деляющее множество вершин, минимальное относительно включения, есть клика. Кликой называется порожденный подграф являющийся полным графом и не являю- щийся подграфом никакого другого полного подграфа. Другая характеризация хордальных графов связана с понятием симплициальной вершины. Вершина v называется симплициальной тогда и только тогда, когда ее окре- стность A(v) (т. е. вершины, смежные с v) порождает полный подграф, или клику. Если v — симплициальная вершина и IV = A(v) о {у}, то G(IV) есть клика и это един- ственная клика, содержащая v
Гпава 1. Графы и сети 35 Б. Граф G является хордальным тогда и только тогда, когда каждый порожденный подграф G(H'’) имеет, по крайней мере, одну симплициальную вершину. Более того, Г Дирак показал, что каждый хордальный граф, отличный от полного, имеет две несмежные симплициальные вершины. Это свойство может быть исполь- зовано для еше одной характеризации хордальных графов. В. Граф — хордальный тогда и только тогда, когда каждый индуцированный под- граф есть либо клика, либо имеет две несмежные симплициальные вершины Близка к последней характеризация, основанная на специальном упорядочении вер- шин. Упорядочение вершин графа vj, ., v„ называется совершенным элиминирую- щим порядком, если для каждого i, v, есть симплициальная вершина в подграфе GV.V ) v . Г. ГрафС — хордальный, если он допускает совершенный элиминирующий порядок. Граф называется степенно-хордальным (power-chordal) тогда и только тогда, когда все его степени хордальны. фДля графа G следующие условия эквивалентны □ G — степенно-хордальный', П GuG2 —хордальные графы ', П существует общее совершенное элиминирующее упорядочение графов G и G2 (т. е. упорядочение вершин, при котором каждая вершина v, симплициальна од- новременно в G, и G2). Хордальные графы могут быть представлены деревьями клик. Указанные деревья изучались с использованием графа пересечения клик, который может рассматривать- ся как гиперграф клик. Развитием этой проблематики служит представление в виде графа клик, который является подграфом графа пересечения клик и может рассмат- риваться как наименьший граф, содержащий все деревья клик. Будем называть раз- рез, отделяющий вершину а от несмежной с ней вершины Ь, (а, Ь)-сепаратором. Из- вестно, что минимальные сепараторы хордальных графов и полные подграфы — это одно и то же. Пусть G = (Г, Е) — хордальный граф. Граф клик для G, обозначаемый C(G) = = (К, Е„ р), где р: Ес. —> W определяется следующим образом: I. Множество Vc вершин графа C(G) есть в точности множество максимальных клик графа G. 2. Ребро (С|, СГ) принадлежит Ес тогда и только тогда, когда пересечение С, п С2 — минимальный (а, £>)-сепаратор для каждой а е (С, \ С2) и каждой b е (С2 \ С,). 3. Ребрам (С„ Q) е Ес приписан вес р(С„ Q), равный мощности соответствующего минимального сепаратора. Заметим, что граф клик хордального графа сам необязательно является хордальным. Подклассами хордальных графов являются: □ деревья; □ интервальные графы;
36 Часть I. Обработка и визуализация графов □ расщепляемые графы (split graphs); □ строго хордальные графы (strongly chordal graphs); □ дважды хордальные графы (doubly chordal graphs); □ хордальные графы сравнимости (chordal comparability graphs). Интервальные графы Интервальным графом называется граф пересечений множества замкнутых интерва- лов вещественной прямой. Е. Пусть G — неориентированный граф. Следующие утверж дения эквивалентны: П G — интервальный граф', П максимальные клики в G могут быть линейно упорядочены так, что для каждой вершины х в G максимальные клики, содержащие х, встречаются последова- тельно. Напомним также, что порядок P(G), порожденный бесконтурным орграфом G, назы- вается интервальным порядком, если он допускает интервальное представление {Л}леи вещественными компактными интервалами такими, что для всех х, у е И имеем: х < у в P(G) тогда и только тогда, когда г(Д) < /(/>.) в R, где /•(/) (соот- ветственно /(/)) правый (соответственно левый) конец интервала /. Строго хордальные графы Пусть N(v) — окрестность вершины v, и пусть A'[v] = N(v) о {v} — замкнутая окрест- ность вершины V. Пусть GJ = G({vy,..., v„}), тогда M[v] — замкнутая окрестность v в G,. Упорядочение вершин (v(, ..., v„) называется строго элиминирующим порядком тогда и только тогда, когда для всех /е {!,..., п} имеет место включение M[vJ с 7V,[v*], если vj, е 7V,[vJ иj <k. Граф G называется строго хордальным тогда и только тогда, когда G допускает стро- го элиминирующий порядок. 1.1.4. Алгоритмы распознавания и раскраски Алгоритмы распознавания Различают много разных видов графов. Обычно существуют теоретические и прак- тические причины изучать специальные классы графов и может быть чрезвычайно полезно исследовать проблемы графовых алгоритмов вначале на специальных клас- сах графов. Это приводит к важной проблеме распознавания, когда относительно каждого типа X интересуются: принадлежит ли данный граф типу XI К поставленно- му вопросу близки и другие: для данного графа G и целого к можно ли перевести граф G в класс X добавлением или удалением к вершин или ребер? Известно множе- ство вариантов этого вопроса. Интересно, что проблема распознавания для классов графов может быть достаточно непростой. В связи с этим от каждого класса графов требуется, чтобы его алгоритм
Глава 1. Гоафы и сети 37 распознавания имел полиномиальную оценку трудоемкости. В табл. 1.1 представлен перечень оценок для некоторых классов графов. Таблица 1.1. Перечень оценок сложности распознавания для некоторых классов графов Категория Класс графов Сложность распознавания Деревья и близкие к деревьям графы Деревья/леса Линейная Почти деревья(Л) Линейная Древесная ширина—к Оф2) для фиксированного к Ширина полосы (к) Полином от п для фиксированного к Степень к Линейная Планарные графы Планарные Линейная Последовательно- параллельные Линейная Внешнепланарные Линейная Граф Халина Линейная Л-внешнепланарные Полиномиальная Решетки Линейная Свободные от K3i Линейная Толщина к Л'Р-полная для к > 2 Род к М’-полная для произвольного к Оф2) для фиксированного к Совершенные графы Совершенные В классе co-NP Хордальные Линейная Расщепляемые Линейная Строго хордальные Полиномиальная Планарные совершенные Сравнимости О(А — т), где А = max deg Двудольные Линейная Перестановок Оф3) Кографы Линейная
38 Часть I. Обработка и визуализация графов Таблица 1.1 (окончание) Категория Класс графов Сложность распознавания Г рафы пересечений Неориентированный путь О(п) Ориентированный путь Otf) Интервал Линейная Дуга окружности О(л3) Окружности Полиномиальная Собственные дуги окружностей Пол ином иальная Ребра Линейная Свободные от клешней Линейная Часто возникают следующие вопросы. Принадлежит ли заданный граф типа Л'также и к типу У? Обладает ли данный граф типа X свойством /’? (Под "свойством" подра- зумевается любое теоретико-графовое свойство, например, свойство графа "быть га- мильтоновым" и т. д.) Кроме того, многие теоретико-графовые конструкции могут быть специализированы для графов некоторого типа X с более низкой трудоемкостью реализации. Алгоритмы раскраски Рассмотрим проблему раскраски ребер графа G, при которой никакие два смежных ребра не раскрашены подобно. Такое распределение цветов называется (собствен- ной) раскраской ребер. Аналогично можно определить раскраску вершин графа G такую, что никакие две смежные вершины не окрашены подобно. В этом случае бу- дем говорить о (собственной) раскраске вершин Граф G k-реберно (вершинно) рас- крашиваем, если существует собственная окраска, использующая к цветов. Реберно-хроматическим индексом ye(G) называется наименьшее число цветов, необ- ходимых для собственной реберной раскраски графа G. Аналогично определяем вершинно-хроматический индекс ЧЛ(С) или хроматическое число y(G) как наимень- шее число цветов, требуемых для собственной вершинной раскраски графа G. Реберная раскраска Очевидная нижняя оценка для vpc.(G) есть максимальная степень А графа G. Это свя- зано с тем, что семейство ребер, инцидентных любой вершине, должно быть окраше- но в различные цвета. Фактически, для любого простого графа G справедливы нера- венства Визинга'. А < \j/,.(G) < А + 1. Для двудольных и полных графов эти неравенства приобретают следующий вид: □ если G — двудольный граф, то чд.(О) = А; □ если G— полный граф с п вершинами, тогда 44(G) = А, если п четно, и 44(G) = А 4- 1, если п нечетно.
Гпава 1. Графы и сети 39 Вершинная раскраска Переходя к вершинной раскраске, заметим, что вопрос о том, имеет граф или нет собственную вершинную раскраску, использующую менее к цветов, является NP- полной задачей. Справедливы следующие свойства. А. Любой граф G является Е+Х-вергиинно-раскрагаиваемым графом. Теорема Брукса. Если G не является полным графом, но связен и для него А > 3, то G является к-вершинно-раскрашиваемым графом. Так как невероятно, чтобы задача нахождения \gv(G) имела полиномиальную слож- ность, необходимо искать ее решение в терминах приближенных алгоритмов. Однако эта проблема, как и много других, не кажется аппроксимируемой. В качестве приме- ра рассмотрим алгоритм, который использует очевидную эвристику, состоящую в нумерации цветов целыми числами, а вершина окрашивается в цвет с наименьшим номером, неиспользованным при окраске соседей. Такая схема называется последо- вательной раскраской. Пусть цвет вершины v, есть С(г,) и элемент /V„[/] булевского массива есть true, если сосед вершины v, окрашен в цвет J. Вначале каждый 7Vv,[/] имеет значение false. Легко увидеть, что алгоритм, включающий все инициализации, имеет сложность О(п2). Поведение этого алгоритма очень чувствительно к порядку, в котором раскрашиваются вершины. Рассмотрим, например, двудольный граф G = (И, Е), где V разбивается на два под- множества И„ = {i/j, иг, . ., щ} и Vv— {vb v2, .., v*}, где Е= {(?/,, vy)| i*j}. Легко уви- деть, что если вершины окрашиваются в порядке W|, и2, ..., uk, vb v2, ..,vk, тогда граф раскрашивается в наименьшее число цветов. Но если вершины раскраши- ваются в порядке: «1, V|, и2, v2,..., uk, vk, то тогда алгоритм затратит к = '/2 п цветов. Таким образом, если мы определим от- ношение С/Со, где С есть число цветов, использованных алгоритмом, а Со есть опти- мальное число цветов, то увидим, что это отношение может быть произвольно боль- шим. Модифицировать алгоритм можно так, чтобы получить повышенную произво- дительность для многих графов. Однако неизвестен полиномиальный алгоритм, для которого отношение производительности было бы ограничено константой. Известное отношение производительности О(п log и). Фактически существует лишь малая на- дежда отыскания алгоритма с полиномиальной трудоемкостью и хорошим отноше- нием производительности, поскольку показано, что если существует приближенный алгоритм с отношением производительности, равным два или менее, то тогда было бы возможно найти оптимальную раскраску за полиномиальное время. Рассмотрим некоторые практические приложения раскраски графов. Классический пример таких приложений — составление расписаний. В крупных учебных заведени- ях возникают проблемы составления расписания использования аудиторий так, что- бы оно согласовалось с существующей нагрузкой преподавателей. Ограничительным фактором является то, что многие аудитории не могут быть спланированы на одно и то же время, поскольку должны посещаться одними и теми же студентами. Как мо-
40 Часть I. Обработка и визуализация графов жет действовать составитель расписания, чтобы сократить время составления распи- саний до минимального? Одно решение состоит в том, что лекции представляются вершинами графа, в котором ребра связывают две вершины, если соответствующие лекции не могут планироваться на одно и то же время. Хроматическое число такого графа соответствует минимальному времени, требуемого для завершения всех за- нятий. 1.1.5. Кратчайшие цепи В неориентированном графе под длиной цепи подразумевается число ребер, обра- зующих цепь. Пусть, далее, каждому ребру е сопоставлено некоторое вещественное положительное число и(е), называемое весом ребра, причем вес цепи, порождаемой ребрами еь е2, ., ек, определяется как сумма весов составляющих ее ребер Вес реб- ра (цепи) называется также длиной; стоимостью и т. д. Цепь (2о(г.w) называется кратчайшей цепью, если ее длина является наименьшей среди длин всех цепей, соединяющих и и v. Большинство полученных результатов, касающихся расстояний в графах, получены для ориентированных графов, аналогичные результаты для неориентированных гра- фов получаются автоматически, см. разд. "Кратчайшие пути" данной главы. 1.1.6. Задача о минимальной связке Пусть Х„ = {xi, х2, — множество точек на плоскости Минимальным деревом Штейнера называется сеть в виде дерева с минимальным весом (сумма весов входя- щих в сеть ребер). К множеству вершин минимального дерева Штейнера могут отно- ситься и дополнительные вершины — точки Штейнера. Подобная задача может быть поставлена и на неориентированных графах. Пусть да- ны граф G = (K Е) и некоторое подмножество X его вершин. Задача состоит в сле- дующем: построить частичный граф Я=(К, Е') с наименьшим суммарным весом его ребер, содержащий все вершины из X. Данная задача носит название задачи о мини- мальной связке. Для произвольного множества X эта задача— /УР-полная. Эффек- тивно решаются только две задачи: для |А] = 2 задача вырождается в задачу о крат- чайшей цепи, для рУ| = 3 задача решается следующим образом. Пусть X- {а, б, с}. Решаем трижды задачу о кратчайшей цепи для вершин {а, Ь, с}, указывая в качестве источника вершины а, Ь, с. Тогда для каждой вершины будут вычислены три чис- ла— расстояния от а, от Ь и с. Просуммируем их для всех вершин. Пусть х0— вер- шина с наименьшей суммой. Эта вершина (вершина Штейнера) соединяется крат- чайшими цепями с вершинами {а, Ь, с}, что и дает решение поставленной задачи. 1.2. Орграфы и сети Орграфы являются основным объектом исследований в так называемой прикладной теории графов, поскольку большинство исследуемых граф-моделей сложных систем представляются орграфами. Например, орграфы моделируют поток информации че- рез граф-модель, используя импульсную модель, согласно которой через входную
Глава 1. Графы и сети 41 вершину граф-модели в систему поступает некоторое количество информации в виде импульса, который генерирует импульсы в соседних с входной вершинах. При этом дуги интерпретируются как операторы, воздействующие на пересылаемые по ним импульсы Обработка информации завершена, если процесс перемещения импульсов прекращается и на выходе системы появляется требуемая информация. 1.2.1. Орграфы Большинство определений из разд. / / переносятся на орграфы путем незначитель- ной их модификации. Орграфом называется пара (У, А), где У— непустое множество объектов некоторой природы, называемых вершинами орграфа, а А - подмножество двухэлементных упорядоченных подмножеств множества У, называемых дугами орграфа (рис. 1.8). Множества вершин и дуг орграфа G обозначают l'(G) и A(G), соответственно. Если |E(G)| = п и p4(G)| = m, то говорят о (и, т)-орграфе G. Орграфом называется пара (У, А), где V— множество вершин графа, а Е— множест- во дуг— есть подмножество множества У2 / — классов эквивалентности, на которые множество И_2= {(v, w) | v е и’} разбивается отношением эквивалентности: (V|, И'|) ~ (v2, М’2) <=> (v,, М’|) = (v2, w2) Орграфом называется набор (У, A, Pt, РГ), где V— множество вершин, А — множест- во объектов некоторой природы, отличной от природы вершин, называемых дугами, Pt — инциденпюр, сопоставляющий каждой дуге е е А вершину v, называемую нача- лом дуги, а Р2— инцидентор, ставящий в соответствие дуге е вершину и> из У, назы- ваемую концом дуги. Дуги орграфа, как и вершины, и ребра графа, называются также элементами графа. Для дуги е = (v, w) вершины v, w е lz(G) называются соответственно началом (или головой) и концом (или хвостом) дуги. Можно также определить кратные дуги и ор- мулыпиграф. Дуга вида (v, v) называется ориентированной петлей Замечание. В практике работы с теорией графов нет необходимости использовать термин "орграф" и связанные с ним термины. В большинстве случаев можно упот- реблять термин "граф" как более общий, если это не приводит к недоразумениям. Чаще всего из контекста ясно, что здесь имеется в виду. Связность орграфов Пусть V|, v2,..., v„Vi i, ,,vk— последовательность вершин такая, что каждая пара соседних вершин v„ vj+) определяет дугу в орграфе, дуги ориентированы в направле- нии движения от у, к v*. Указанная последовательность называется ормаршрутом или путем. Ормаршрул называется простым путем, если ни одна вершина не встре- чается в нем дважды. Вершины V| и vk называются началом и концом пути соответст- венно. Орграф называется сильно связным, если каждая пара вершин в орграфе соединена путем (рис. 1.9).
42 Часть I. Обработка и визуализация графов Рис. 1.8. Орграф: а — орграф общего вида, б — матрица смежности Рис. 1.9. Связность орграфов: а — сильносвязный орграф, б — слабосвязный орграф, в — односторонне связный орграф
Глава 1. Графы и сети 43 Назовем контуром путь, у которого совпадают начало и конец. Контур считается простым, если ни одна вершина не встречается в нем дважды. Назовем цепью или полупутем в орграфе такую последовательность дуг, в которой дуги могут совпадать с направлением от начала цепи к ее концу или не совпадать. Замкнутая цепь называ- ется циклом (в орграфе). Сильная связность есть бинарное отношение эквивалентности. Класс эквивалентно- сти называется компонентой сильной связности. Максимальная по включению ком- понента сильной связности называется бикомпонентой. Можно утверждать, что че- рез любые две вершины бикомпоненты проходит контур (возможно не простой). Орграф называется слабо связным, если любые две вершины соединены цепью (см. рис. 1.9). Назовем основой/ орграфа D неориентированный граф GD, получаемый из D заменой всех дуг на ребра. Из определения слабой связности следует, что орграф слабо свя- зен, если его основа связна. Орграф называется односторонне связным относительно вершины s, если для любой вершины существует путь из s в эту вершину (см. риб. 1.9). Достижимость Понятие достижимости является одним из фундаментальных понятий в прикладной теории графов. Вершина w достижима из v, если существует путь из v в w. Из приведенных определений следует, что в односторонне связном графе каждая вершина достижима из s. Отношение достижимости задается либо матрицей дости- жимости, либо списками достижимости. Под матрицей достижимости R(D) пони- мают квадратную п* п матрицу, в которой элемент rtJ = 1, если вершина v, достижи- ма из вершины V,, и r,f = 0 в противном случае Понятие достижимости тесно связано с понятием транзитивного замыкания, подробную информацию см. в гл. 3. 1.2.2. Кратчайшие пути Пусть G = (К, Е, w)— взвешенный орграф. Для s, t е К положим l(s, f) равным весу наименьшего по весу пути из s в t. Пусть л„ есть путь из s в t с весом /(s, t) при усло- вии, что такой путь существует. Как и в других случаях работы с взвешенными гра- фами, мы полагаем вес пути равным сумме весов дуг, его образующих. Если вес каж- дой дуги в графе равен 1, то наименьший по весу путь является "кратчайшим" путем в обычном смысле. Для А,Вс V(А, В)— задача отыскания кратчайшего пути за- ключается в определении самого короткого пути (и его длины) из s в / для каждой вершины 5 е А и I е В. Задача считается хорошо определенной, если выполняются следующие предположения: 1. Для каждой вершины s е А и Т е В существует путь из s в (. 2. Никакой путь из s в t не содержит контур отрицательной длины. Традиционно задачи о кратчайшем ({.у}, К)- и (К, Е)-путях привлекают основное внимание. Эти задачи известны как задачи с "единственным источником" и "между всеми парами вершин", соответственно.
44 Часть I. Обработка и визуализация графов Кратчайшие пути с единственным источником Пусть s— фиксированный источник и пусть предположения 1 и 2 выполняются. По- строим дерево кратчайших расстояний ((Л’Т)-дерево) как некоторое остовное ордере- во с корнем в j такое, что путь по дереву из j в t есть кратчайший путь из s в / для всех t е V. Будем писать 1(f) для l(s, f), l(s) = 0. А. Если предположения 1 и 2 выполнены, то существуют SP-деревья для каждой s. Если значения 1(f) известны для всех t е V, то тогда SP-дерево может быть по- строено за время О(т). Это свойство показывает, что мы можем ограничить задачу вычислением весов 1(f). Чтобы сделать это, следует рассматривать 1(f) как решения множества уравнений, известных как уравнения Веллмана'. «5=0 и, = min >3f) {их + w(x, /)} для t*s (величины и, для t^s— неизвестные). Можно показать, что когда G не имеет отри- цательных контуров, решение уравнений Веллмана единственно. Иначе оно единст- венно при дополнительном предположении, что Е, щ максимальна среди всех реше- ний. Таким образом, длины кратчайших путей являются решениями следующей за- дачи линейного программирования (полагаем wfoy)= 00 Для (х,у) £ £).) максимизировать. Е, и, при условии: «л = 0, щ < их + w(x, f) для t е 5, х. Мы не будем дальше исследовать связь с линейным программированием, но некото- рые методы решения уравнения Веллмана прямо входят в эту теорию. Тем не менее, эта характеризация наводит на мысль использовать следующую общую стратегию вычисления решения и построения Л'Р-дерева (обозначая через f(f) указа- тель на предка f): Алгоритм Форда Дано Взвешенный орграф G = (V, Е, и»), удовлетворяющий предположениям 1 и 2. Требуется. Дерево кратчайших расстояний5Р-дерево. Метод. начало 1 Положить us - 0, щ = оо для t е s, f(f) = nil для всех t. 2 . пока не все неравенства удовлетворены цикл 3 . Определить t е s, для которого существует x*tcut> и,= w{x, t); 4 Положить щ= ик + w(x, t) и f(f) = x все конец
Гпава 1. Графы и сети 45 Этот алгоритм сходится вне зависимости от того, какой делается выбор на скани- рующем шаге, при условии, что выполняются предположения 1 и 2. Некоторые ска- нирующие порядки могут быть лучше других и этим различались разные разрабо- танные алгоритмы. (Некоторые порядки могут привести даже к экспоненциальной трудоемкости.) Простой пример дает бесконтурный граф. Другой эффективный порядок сканирования существует, когда w(x, у)>0, хотя он требует больше работы на каждом шаге для выявления правильной вершины t (на- пример, из подходящей структуры данных). Пусть F— множество вершин t, для ко- торых и, уже имеет финальное значение, и пусть множество I вершин, для которых неизвестно, является ли w, финальным значением В начале F= {.$} и / = P\{s}. Алго- ритм приобретает следующий вид. Алгоритм Дейкстры Дано. Взвешенный орграф G = (F, Е, w), удовлетворяющий предположениям 1 и 2, в котором и'(.г,_у) = 0 для всех х и у. Требуется. Дерево кратчайших расстояний SP-дерево. Метод. начало 1. Положить us = 0. ut= w(s t) для t*s, f(t) = s для всех t; 2. пока I * 0 цикл 3. Выбрать tel, для которой ut минимально; 4. для каждого соседа х е I вершины t цикл 5 Положить их = min{ux, ut + w(x, f)} и положить f(x) = t, когда Ut + w(x, t) был меньше чем ux все все конец Данный алгоритм требует О(т) операций, кроме операций для реализации очереди с приоритетами для значений их (выбор и удаление элемента на шаге 3 и deg(/) опе- раций на модернизацию очереди на шаге обновления 4). Простой список приводит кО(и) шагов на итерацию и к общей трудоемкости О(гг), а также O(deg(r)-log(n)) ша- гов на итерацию для работы с очередью с приоритетами и, следовательно, приводит к общей трудоемкости С)(т log(/?)). Кратчайшие пути для всех пар вершин Задача о кратчайших путях для всех пар вершин допускает широкую гамму методов решения и иллюстрирует лучше других графовых задач допустимую технику реше- ния. Допустим, что предположения 1 и 2 (см. с. 43) по-прежнему соблюдаются, в ча- стности, будем предполагать, что отсутствуют отрицательные контуры. Очевидный подход состоит в решении и задач о кратчайшем пути с единственным источником по одной для каждого возможного источника. Результирующая трудоемкость равна 0(пт + и2 log(n)) для графов с неотрицательными ребрами и О(и2Л4) в общем случае.
46 Часть I. Обработка и визуализация графов Ряд методов основан на использовании степеней матрицы смежности А(„ а также на методе Флойда — Уоршалла отыскания транзитивного замыкания. 1.2.3. Генерация путей В этом разделе мы будем предполагать, если не оговорено противное, что рассматри- ваемые графы — невзвешенные неориентированные графы, хотя большая часть ре- зультатов имеет смысл и для ориентированных графов. Говоря о путях и контурах в графах, мы будем иметь в виду как пути и контуры орграфов, так и цепи и циклы неориентированных графов. Пути длины к Вероятно, простейшим является вопрос: для данного к имеется ли в графе (простой) путь длины к из i в у. Эта задача может быть решена за время О(к(п - Т)к ') путем рассмотрения всех возможных комбинаций (4-1) промежуточных вершин и отбра- сывания тех комбинаций, которые не порождали путей. Получить эффективное ре- шение до удивления трудно. В самом деле для произвольного к задача /VP-полна и, таким образом, скорее всего, не может быть решена за полиномиальное время. Имеет место следующее свойство. А. Пусть G— (ориентированный или неориентированный) граф и к>0. Тогда путь длины к может быть вычислен (с некоторой индикацией для всех пар вершин, для которых не существует путь длины к) за время О(к\ пт). Применяя это свойство, можно найти самый длинный путь в G за время О(ц + 1)! пт). Здесь ц — длина самого длинного пути. Для решения этой задачи нужно искать пути длины к для к = 1,2, 3,..., пока не будет получено последнее значение, для которого найден путь. Для любого фиксированного к существует алгоритм с трудоемкостью О(п) для ответа на вопрос: имеет ли граф (простой) путь длины > к или нет. Различные непересекающиеся пути Рассматрим только вершинно-различные пути (случай реберно-различных путей также интересен). Задача нахождения максимального множества вершинно-различ- ных путей между вершинами / и j весьма полезна для многих сетевых задач. Некото- рые алгоритмы для этой задачи используют связь с 0-1 максимальным потоком, что делает ее полиномиальной (с полиномом от я и т). Б. Число вершинно-различных путей между’ i и j может быть найдено с помощью максимального потока в расширенном (ориентированном) графе G cln вершинами, 1т + п дугами и дугами с пропускной способностью 1. Использование этого свойства для конструирования вершинно-различных путей при- водит к слишком сложному алгоритму. Например, если необходимо найти к вершин- но-различных путей между / и j (в предположении их существования) с помощью эксплуатации их связей с целочисленным потоком, то будет ясно, что в этом случае нужно найти (и проследить) только к расширенных путей для получения потока > к.
Глава 1 Графы и сети 47 Может быть полезной связь с оптимальными (минимальной стоимости) потоками. Известен алгоритм для нахождения множества к вершинно-различных путей с наи- меньшей общей длиной. (Не был проведен анализ трудоемкости.) Теорема Менгера дает необходимое и достаточное условие для существования вершинно-различных путей. Простое и практическое обобщение этой задачи состоит в следующем: пусть даны I пар Oi,ji),..., (ч,/1); существуют ли в G / вершинно-различных путей, связывающих ц иjk по одному для каждого к, 1 <к<1. (Известно много вариантов таких обобщений, например, каждую пару можно было бы соединять более чем одним путем.) С произ- вольными G и к данная задача известна как задача о непересекающихся связываю- щих путях, а также, что она ЛТ-полна. Генерация всех s-t-путей Рассмотрим алгоритм перечисления всех простых s-/-путей в обыкновенном орграфе с использованием оператора склейки. Пусть орграф D = (V,A) задан списком дуг D = {е,„| е,„ = <//, х,у), и = (х,у), и с А} Работа алгоритма состоит в последовательном удалении вершин (исключая i и /) и одновременной замене дуг, заходящих и исходящих из удаляемой вершины, их склейками— отрезками путей из х в /. Склейка дуг и отрезков путей производится оператором склейки Д, который заменяет список путей из {х,} в удаляемую вершину х — список S — и список S путей из х в {у,} одним списком путей S ДЗ из {х,} в {у} При этом возникающие во время работы алгоритма отрезки путей обозначаются аналогично дугам, т. е. тройкой (цА, х„ уф, где х, — начало пути щ, а у, — его конец. Перечисление всех путей в графе В основе метода решения поставленной задачи лежат следующие свойства. В. Пусть G = (V Е) u Н = (V, U) — два орграфа с одним и тем же .множеством вер- шин и с матрицами смежности A(i = ||а;/|| и АИ = ||Ь,,||, соответственно. Матрице А(;*Ан— произведению .матриц Ас, и Ан отвечает мультиграф, образованный следующим образом: из вершины х, в вершину х, идет столько дуг, сколько существу- ет различных путей, ведущих из х, в х, и составленных из двух дуг, первая из которых принадлежит Е, а вторая — U. Г. Элемент рч матрицы Р = Ав, полученной возведением матрицы смежности Ас графа G в степень 6, равен числу различных путей длины 6, идущих из х, в х,-. Уточним определение оператора склейки Д двух простых путей ц, = [хл,..., х,г„ х*] и р2 = [х/, х;1,..., х/¥]: Ц|Др2= [хд, —, XiP, xk, x/h ..., x/<z], если х* = х, и получившийся путь простой. В противном случае порождается пустая последовательность вершин. Если = {ць Ц2, , Цг, , Цд} есть множество путей из х, в х* длины р, а Мхщ = {И, И, ..., V;} есть множество путей длины q изх*вху, то М^ГХМ^ф есть множество простых путей из х, в х,.
48 Часть I. Обработка и визуализация графов Для любых целых положительных чисел пи имеем = и АЛ/дцД Исходя из указанных соотношений, видно, что это есть не что иное, как определение "умножения" матриц с буквенными элементами |M(r+s) = ||Л/]|(л) Л||Л/]|1') Беря в качестве ||Л7)| = |риЛ матрицу смежности A(G), записываемую в виде 1х,х,, если а..-1, '' (0, в противном случае, нетрудно убедиться в том, что ||Л/]|(|^ есть матрица путей длины 1, ||ЛТ]|(2) = ||Л/]|(|,Л ||М]|(1> — матрица путей длины 2 и т. д. 1.2.4. Генерация контуров Существует довольно много алгоритмов генерации всех контуров в орграфе Рас- смотрим простой алгоритм, принадлежащий Вейнблату, на примере которого можно обсудить типичные черты таких алгоритмов генерации. Считаем, что орграф задан списками смежности. Без ограничения общности полагаем орграф сильно связным. В произвольном графе имеются компоненты сильной связ- ности и любой контур принадлежит одной и только одной бикомпоненте, поэтому для перечисления всех контуров достаточно найти все бикомпоненты и применить алгоритм к каждой бикомпоненте. Введем некоторые вспомогательные определения и обозначения. Состоянием S(x) вершины х будем называть переменную, принимающую одно из трех значений: 0, если вершинах еще не рассматривалась, I, если вершинах рассмат- ривалась и находится в "активной" зоне, и 2, если вершина х рассматривалась и уда- лена из активной зоны. Аналогично определяется состояние S(u) дуги и за исключением того, что дуга имеет только два значения: 0, если дуга не рассматривалась, и 2, если дута и рассматрива- лась и исключена из дальнейшего рассмотрения. Текущим списком ТТ будем называть запись простого пути из некоторой начальной вершины до исследуемой. В общем случае эта запись включает в себя как вершины, так и дуги. Легко увидеть, что текущий список ТТ реализуется с помощью стека. Первой вершиной контура или головной вершиной будет называться та вершина кон- тура, которая встречается первой в списке ТТ Алгоритм 1.1. Отыскания всех контуров в графе Дано. Сильно связный орграф, заданный списками смежности. Требуется. Список контуров.
Глава 1. Графы и сети 49 Метод. проц Concat(P) = 1. Организовать вначале пустой вспомогательный список проверяемых частей контуров; v = End(P). 2. Осуществляем просмотр списка контуров для отыскания тех из них, запись которых содержит и. 3. Если контур не содержит вершины v или часть Tail(CP,v), содержащая вершину и уже помещена во вспомогательный список, то переходим к шагу 10. 4. Добавляем найденную часть с вершиной v во вспомогательный список. 5. Если часть контура содержит какую-нибудь вершину из Р, то переходим к шагу 10. 6. Если S(End(CP)) = 2, где End(CP) — последняя вершина в записи контура СР, то Recur = 1. Вызываем процедуру Concat со значением параметра Р= ТаЩСР, и),после ее завершения переходим к шагу 10. Если S(End(CP)) = 1, то организуем новый контур с начальной вершиной End(CP) 8. Если Recur = 0, то добавляем новый контур к списку проверяемых частей контуров и переходим к шагу 10 9. Если С не находится среди тех контуров, которые были добавлены к списку контуров, созданных с момента последнего внешнего (т. е последнего вызова с шага 4 основного алгоритма) обращения к процедуре Concat, тогда добавляем С к списку контуров. 10 Продолжаем шаг 2, если возможно. все начало 1. % Инициализация % Полагаем для каждой вершины х S(x) = 0 и для каждой дуги u S(u) = 0; ТТ =0; 2 % Выбор начальной вершины % Находим произвольную вершину и такую, что S(v) = 0; в противном случае — СТОП. ТТ<- ц S(v)= 1; 3. % Удлинение списка % Находим дугу и, которая выходит из вершины End{TT) последней в списке ТТ, и у которой S(u) = 0; если такой нет, то полагаем S(End(TT}) - 2, удаляем End(TT') из списка ТТи переходим к шагу 5; ТТ=ТТ— u; S(u) = 2; 4. % Исследование конечной вершины дуги и % Пусть v — конец дуги и. Если S(v) = 0, то ТТ ТТ — и; S(v) = 1 и переход к шагу 3; Если S(v) = 1, то это означает, что в списке ТТ содержится контур с начальной вершиной и. Часть списка ТТ, начинающуюся с и и заканчивающуюся v, переносим в список контуров. Переход к шагу 5;
50 Часть I. Обработка и визуализация графов Если S(u) = 2, полагаем Recur- 0, вызывает процедуру Concat(P) со значением параметра Р, равным и; после завершения работы процедуры переходим к шагу 5; 5. % Завершение % Удаляем последнюю дугу из списка ТТ Если список ТТ пуст, то переход к шагу 2, в противном случае — к шагу 3. конец Замечание. При практическом использовании алгоритм может быть упрощен пу- тем удаления несущественных деталей Например, можно обойтись записью путей только с использованием вершин. 1.2.5. Сети и задачи о потоках Сетью называется граф (или орграф), в котором выделены специальные вершины — "полюса" и ребра/дуги снабжены операторами, влияющие на передаваемые по ним сигналы Одними из самых распространенных граф-моделей такого вида служат так называемые потоковые сети. С их помощью можно решать задачи, связанные с по- строением множеств путей, покрывающих вершины или дуги/ребра графа. Пусть дана ориентированная двухполюсная сеть G(s, q) = (V, Е, s, q) с входом л и вы- ходом q, каждой дуге которой сопоставлено натуральное число с(е)>0, называемое пропускной способностью дуги е. Заметим, что случай перевозок однородного груза по многополюсной сети с входами st,..., и выходами q\,..., qt легко сводится к двухполюсному случаю введением фиктивных входа .s'() и выхода q0. Величина с(е), е е £, ограничивает объем перевозимого по дуге е груза. Требуется обеспечить пере- возку Р единиц размещенного (или производимого в s) груза по сети G, не допуская превышения пропускных способностей дуг. Математической моделью задачи о пере- возках служит наибольший поток. Потоком f по сети G называется целочисленная функция, определенная на множест- ве дуг Е и удовлетворяющая следующим условиям: 1 0<У(е)<с(е). 2 . £/(v,w) = £/(w,x), w*s,q. V X Первое суммирование ведется по дугам, заходящим в w, а второе — по дугам, исхо- дящим из w. Число Ff = называется величиной (мощностью) потока f По- V V ток/, величина Fo которого наибольшая из всех возможных потоков по сети G, на- зывается наибольшим потоком. Очевидно, что если Р = Fo, то построение наибольшего потока полностью решает задачу; при Р> Fo задача не имеет решения, при Р < Fo решение сводится к построе- нию ограниченного по величине потока.
Гпава 1. Графы и сети 51 Если дугам е сети G сопоставлены числа Ь{е) — стоимости перевозки единицы груза по дуге е, то величина B(j)= У/(e)fe(e) называется стоимостью потока f Наи- е больший поток с минимальной стоимостью называется оптимальным потоком. По- ток произвольной величины Fj, 0 < Fj < Fo, с наименьшей стоимостью называется оптимальным потоком величины Fj. Известно, что от одного потока / к другому f2 той же мощности можно перейти с помощью операции сдвига на цикле Однако, более эффективным является последо- вательное построение оптимального потока с помощью отыскания увеличивающей поток цепи наименьшей длины. Отыскание цепи проводится алгоритмом Дейкстры, считая длину (стоимость, время перевозки) дуги с ненулевым потоком, проходимую против ориентации, отрицательной. Достоинством этого подхода является то, что мы на каждом шаге имеем цепное разложение потока. Другими словами, на каждом ша- ге алгоритма построения потока мы имеем множество 5, g-путей (хотя речь идет о цепном разложении) {Р|,..., Рг} таких, что для каждой дуги е имеем /е)= ХЛ(е), k\ft эе где суммирование ведется по всем путям Рк, содержащим дугу е. Нетрудно увидеть, что с помощью наибольшего потока эффективно решается задача о нахождении множества попарно непересекающихся путей между заданными вер- шинами, что позволяет определить реберную связность в соответствии с теоремой Менгера. С этой целью необходимо положить пропускную способность дуг, рав- ной 1, заменить каждую вершину v двумя вершинами v' и v" так, чтобы все дуги, за- ходящие в v, заходили бы в v', а исходящие из v исходили бы из v". Полученную пару вершин v' и v" соединим дугой (v', v") с пропускной способностью равной 1. Можно утверждать, что цепное разложение построенного наибольшего 0-1 потока дает сис- тему путей, соответствующих теореме Менгера. Будем считать, что каждой дуге е сети сопоставлено число г(е) > 0, называемое ниж- ней пропускной способностью. Тогда минимальным потоком по сети с ограничения- ми на поток снизу называется целочисленная функция <р(е), удовлетворяющая двум условиям: ip(e) > г(е); £<p(v, w) =^<p(w,x), w*s,q; V X и которая минимизирует величину потока. Нетрудно увидеть, что цепное разложение минимального потока, построенного для случая, когда все нижние пропускные способности равны 1, эффективно решает за- дачи построения вершинных и дуговых покрытий.
52 Часть I. Обработка и визуализация графов 1.2.6. Алгоритм Форда — Фалкерсона Алгоритм построения наибольшего потока по сети с одним входом и одним выходом, предложенный в середине 50-х годов двадцатого века Л. Фордом и Д. Фалкерсоном, состоит их двух частей: построение полного потока и построение на его основе наи- большего потока. Назовем для данного потока fie) дугу е насыщенной, если для нее выполняется равен- ство fie) = с(е), где с(е)— (верхняя) пропускная способность дуги е. Поток fie) назы- вается полным, если любой х-7-путь содержит насыщенную дугу Тогда процесс по- строения полного потока состоит в последовательном построении х-7-путей, не со- держащих насыщенных дуг, и увеличении суммарного потока по сети за счет пропуска дополнительного потока по построенному s-7-пути. Пусть теперь Де) — полный поток по сети Следующая процедура проверяет, являет- ся ли построенный полный поток наибольшим, и если нет, то увеличивает его. Назовем цепь Q = ((s=) vb v2,..., v*( = t)) г/епыо, увеличивающей поток, если она со- держит хотя бы одну дугу е' проходимую (при движении из х в t) против ее ориента- ции, и такую, чтоДе)>0. Тогда модифицированный поток <р определяется следую- щим соотношением /(е) + Д)(е), если eeQ и проходится по ее ориентации, <р(е) = '</(е)-Д;(е), если eeQ и проходится против ее ориентации, /(е) —в остальных случаях. Здесь — максимальный поток по цепи Q мощности fifie) - min{c'(e),/(e')}, где с'(е)— остаточная после построения полного потока верхняя пропускная способ- ность дуги, {е'} — множество обратных дуг в Q. 1.2.7. Алгоритмы Диница и Карзанова Алгоритм Диница Исследуя алгоритм Форда— Фалкерсона, Эдмондс и Карп заметили, что увеличение потока по кратчайшим путям ведет к полиномиальному алгоритму Для дальнейшего увеличения эффективности Е. Диниц предложил метод нахождения всех кратчайших путей, увеличивающих поток, в одной фазе. Метод Диница основан на построении некоторой вспомогательной бесконтурной сети, структура которой точно отображает все кратчайшие увеличивающие поток цепи из х в г относительно фактического потока /. Обозначим такую сеть через St. Она строится при помощи поиска в ширину в графе Gj с дугами, определяемыми допус- тимыми относительно фактического потока / дугами в исходной сети. Сеть S,содер- жит источник s, сток t и дуги графа G/ вида (г/, v), где и находится на расстоянии d, a v на расстоянии d + 1 от х, 0 < d < I, где / есть длина сети Sf, т. е. расстояние от х до I в графе Gf Пропускную способность с/и, v) определяем как c(w, v) - fin, v) или как fiv, и) в зависимости от того, проходится ли дуга (w, v) по ориентации или нет.
Глава 1. Графы и сети 53 Идея Диница основывается на разбиении процесса увеличения потока вдоль увели- чивающих цепей на фазы, соответствующих использованию кратчайших цепей опре- деленной длины. Фаза начинается с построения вспомогательной бесконтурной сети, затем во вспомогательной сети находится так называемый псевдомаксимальный по- ток. Псевдомаксимапьны.м потоком в сети St длины / называется произвольный поток f в S) такой, что в S) не существует увеличивающей поток цепи длины / относительно потока /; другими словами, для произвольного пути из s в t в S), определенно- го последовательностью вершин v0( = s), vb..., v, ( = f), существует дуга (v„v,u), О < i < /, такая что/*(v„ v,,,) = c/v;_,, t). Псевдомаксимальный поток затем "переносится" из вспомогательной сети в первона- чальную сеть, поток /'(и, v) складывается с flu, v), а если это вызывает переполнение дуги, т. е. превышение потока над пропускной способностью дуги с(и, v), то этот "из- быток" ликвидируется соответствующим уменьшением потока/(v, и) (таким образом, результатом модификации всегда является увеличение Div/zz) = E>,/(w, v) на,/*(zz, v) и уменьшение Div/v) на/*(w, v)). Нетрудно проверить, что такая модификация потока, проведенная для всех дуг (и, v) вспомогательной сети, определяет некоторый новый поток /' такой что W(f') = W(f) + Фазу считаем законченной. Метод Диница основывается на выполнении последовательных фаз, начиная с нулевого потока вплоть до момента, пока поток в рассматриваемой сети не станет максимальным. Метод Диница эффективен в основном из-за того, что независимо от пропускной способности дуг число фаз не превышает и. Алгоритм Карзанова В основе алгоритма Карзанова лежит понятие предпотока. Предпоток подобен пото- ку за исключением того, что полное количество потока, втекающего в вершину, мо- жет превосходить количество потока, исходящего из нее. Назовем избытком пото- ка в вершине v величину e(v), где e(v) = £ ,e|//(z, v). В течение каждой фазы алгоритм Карзанова поддерживает предпоток в бесконтурной сети. Алгоритм проталкивает поток через сеть для нахождения блокирующего пото- ка, который определяет бескошурную сеть для следующей фазы. С этой целью про- веряются вершины, отличные от s и (, с положительным избытком и имеющийся из- быток проталкивается в вершины, расположенные ближе к выходу /, с целью перено- са как можно больше избытка в вершину t. Если выход / не достижим из вершины с положительным избытком, тогда алгоритм будет проталкивать избыток в вершины, расположенные ближе к входу s. В итоге алгоритм достигает такого состояния, в ко- тором все вершины, отличные от s и t, будут иметь нулевой избыток. В этой точке предпоток становится фактически максимальным потоком. Алгоритмы для построения потока и их трудоемкость Реализация алгоритма Диница требует О(пт + nF) времени, где F = F(n,m) есть верхняя оценка времени для определения полного (блокирующего) потока для сети не более чем с п вершинами и т дугами. Исходный алгоритм Диница определяет блокирующий поток отделением некоторых дуг для образования пути из ,s- в t путь за
54 Часть I. Обработка и визуализация графов путем, достигая F= O(nm) и (следовательно) полная трудоемкость равна О(п2т). По- следующие алгоритмы значительно улучшили эффективность алгоритма Диница за- счет конструирования блокирующего потока другими способами и/или путем ис- пользования специальных структур данных. Наиболее эффективная реализация, свя- занная с данными, принадлежит Слеатору и Тарьяну и дает F = О(Л7 log н), откуда следует, что трудоемкость всего алгоритма построения максимального потока равна О(пт log п). В табл. 1.2 приведена хронология создания алгоритмов нахождения мак- симального потока. Если все пропускные способности целочисленны, то подход Габова приводит к алгоритму с трудоемкостью О(пт log U), где U— наибольшая пропускная способность дуги. Агуджа и Орлин разработали более общий алгоритм с трудоемкостью О(пт + п~ log If), основываясь на технике Гольдберга, что было улучшено Агуджой, Орлином и Тарьяном до алгоритма с трудоемкостью О(пт log(«(log (7+2)|/2//и)). Таблица 1.2. Хронология создания алгоритмов нахождения максимального потока Год создания Авторы T рудоемкость 1956 Ford, Fulkercon 1969 Edmonds, Karp O(nrn) 1970 Dinic O(n2m) 1974 Karzanov O(«) 1977 Cherkasky O(n2ni' 2) 1978 Malhotra, Pramos Kumar Maheshwari O(n3) 1978 Galil O(rT3m23) 1978 Galil, Naamad; O(nwi(log n)2) Shiloach 1980 Sleator, Tarjan O(ntn log n) 1982 Shiloach, Vishkin 1983 Gabow O(nm log U) 1984 Tarjan O(n) 1985 Goldberg O(«3) 1986 Goldberg, Tarjan O(nm log(H2/w)) 1986 Ahuja, Orlin O(nm log(n%/)) 1988 Ahuja, Orlin, Tarjan O(nm log(n(log U + 2),2/m))
Глава 1. Графы и сети 55 Существует некоторое число результатов для специализированных сетей, которые достойны быть упомянутыми. Для сетей, у которых пропускные способности рав- ны 1, Эвен и Тарьян доказали, что наибольший поток получается после не более чем О(им, т|/2) шагов в алгоритме Диница. Для сети, в которой все пропускные способ- ности — целые числа и каждая вершина u* s,t имеет единственную входящую дугу с пропускной способностью 1 или имеет одну исходящую дугу с пропускной способ- ностью 1, нужно самое большее 2Г(и - 2)|/21 шагов алгоритма Диница. Задача о потоке наименьшей стоимости состоит в нахождении допустимого потока наименьшей стоимости в сети с ограничениями на пропускную способность и стои- мость пропускания единицы потока по дуге. Эта задача имеет гораздо больше при- ложений, нежели задача о наибольшем потоке. Все известные полиномиальные алгоритмы для этой задачи основываются на идее масштабирования (scaling). Эта идея была выдвинута Эдмондсом и Карпом, которые использовали ее для построения первого полиномиального алгоритма для решения поставленной задачи. Масштабирующие алгоритмы для задачи об оптимальном по- токе создают последовательность Ро, Ph ..., PL задач об оптимальном потоке. Задача Р, получается рассмотрением i наиболее важных битов пропускной способности (масштабирование пропускной способности) или стоимости (масштабирование стои- мости). Первая задача решается легко, потому что все пропускные способности или стоимости равны нулю. Решение задачи Р, помогает решить следующую задачу Pj41. Если все относящиеся к задаче величины имеют самое большее L битов, решение задачи Р;, есть желаемое решение. Таблица 1.3. Трудоемкость алгоритмов для решения задачи об оптимальном потоке Год создания Авторы Трудоемкость 1972 Edmonds, Karp O(ni log((/)(rn + n log и)) 1980 Rock O(m \og(JJ)(m + n log и)) 1980 Rock O(n log(C)(H/n log(n2//w))) 1984 Tardos O(m4) 1984 Orlin O(m2 log(w)(w + n log и)) 1985 Fujishige O(m log(«)(w? + n log и)) 1985 Bland, Jensen O(n log(C)(«w log (n2/m))) 1986 Galil, Tardos Оф2 log(n)(/n + n log и)) 1987 Goldberg, Tarjan O(min (nm log n, n 2m2'2, n) log(nC)) 1988 Goldberg, Tarjan O(nm log(H2/m) min(»i log n, log nC)) 1988 Orlin O(m log n (m + и log и)) 1988 Ahuja; Goldberg; Orlin, Tarjan O(nm log log U log nC)
56 Часть I. Обработка и визуализация графов В табл. 1.3 представлены известные полиномиальные алгоритмы для решения задачи об оптимальном потоке. Время работы алгоритмов дается в терминах числа вершин п. числа дуг т, наибольшего абсолютного значения пропускной способности U и наибольшего абсолютного значения стоимости С. Когда U (или С) встречается в оценке, они предполагаются целыми. Кроме того, мы предполагаем, что использу- ется как вспомогательная подпрограмма решения задачи о кратчайшем пути с трудо- емкостью О(т + и log и), так и подпрограмма решения задачи о наибольшем потоке с трудоемкостью О(нт log(n“//w)). 1.2.8. Изображение графов и сетей В настоящее время графовое представление информации все больше и больше ис- пользуется в различных областях точных и естественных наук. В программировании графовые модели применяются при создании программного обеспечения (управ- ляющие графы, иерархии классов, диаграммы потоков данных), дизайне баз данных (диаграммы сущностей-связей), разработке информационных систем и систем реаль- ного времени (модели компьютерных сетей, графы состояний, сети Петри), а также в системном программировании — при создании теории компиляции и преобразования программ. Вопрос визуализации подобных графовых структур является краеуголь- ным камнем в процессе адекватного отображения информации. Автоматическое размещение графов — это задача конструирования геометрического представления графа, удовлетворяющего набору эстетических критериев. В послед- ние пятнадцать лет эта проблема подвергается интенсивному изучению. Было опуб- ликовано большое количество работ по рисованию графов, а с 1993 года проводятся ежегодные конференции по данной тематике. Тем не менее задача автоматического размещения графов так и остается до конца не решенной, в том смысле, что до сих пор не было предложено универсального метода ее решения. Возникшую ситуацию можно объяснить тем, что алгоритм размещения должен "учи- тывать" такие разносторонние аспекты, как: класс графа, семантика графовой ин- формации, соглашения об изображении, эстетические критерии и ограничения на получаемое изображение. Перечисленные аспекты настолько многогранны, и их вы- бор настолько сильно зависит от случая конкретного применения, что разработка универсального алгоритма на данном этапе не представляется возможной. В связи с данной проблемой был разработан ряд подходов к автоматическому разме- щению графов, которые базируются на фиксации некоторого набора из указанных критериев/аспектов. Так, например, был разработан целый ряд методов, позволяю- щих разместить планарный граф с прямолинейными или ортогональными дугами, или методы, основанные на физической упруго-силовой модели, которые больше подходят для сильно связанных неориентированных графов с прямолинейными реб- рами. Подробную информацию см. в гл. 5.
Глава 1. Графы и сети 57 Библиографический комментарий Данная глава содержит самые общие сведения из теории графов, большинство из которых мо- гут быть найдены в почти любой монографии по теории графов. Первая монография по теории графов и ее применениям появилась в 1962 г. Это была книга К. Бержа [8]. переведенная с французского А. А. Зыковым. Потом появились также перевод- ные книги О. Оре [44], Ф. Харари [52], Р. Басакера и Е. Саати [6], Р Уилсона [50], У. Татта [49]. В 1969 г и в 1987 г. вышли фундаментальные монографии А. А. Зыкова [22—23]. Нако- нец, в 1990 г вышла в свет замечательная книга "Лекции по теории графов" [39]. а в 2002 г. книга Р Дистеля [13] в переводе О. В. Бородина. Среди книг, в той или иной степени ориентированных на разные приложения, следует указать на следующие издания: Ji. Р. Форд и Д. Р Фалкерсоп [51], Н. Кристофидес [37]. Г. М. Адель- сон-Вельский. Е. А. Диниц. А. В. Карзанов [1]. Э. Майника [41], М. Свами и К. Тхуласираман [46]. М. И. Нечепуренко, В. К. Попкова, С. М. Майнагашева и др. [2], X. Пападимитриу и К. Стайглиц [45], сборник "Дискретная математика и математические вопросы кибернетики" [12]. К книгам, специально посвященным применению теории графов в конкретных областях, относятся книги С. Сешу и М. Б. Рида [48]. сборники статей "Исследования по прикладной теории графов" [24] и "Применение теории графов в химии" [46], Б. Г. Миркина и С. Н Родина [42] и др. Книги [53—54] рассматривают вопросы рисования графов. Различным аспектам применения теоретико-графовых методов в программировании уделялось большое внимание в книгах А. П. Ершова [21]. В. Н. Касьянова [26], С. С. Лаврова [38], В Е. Котова [35]. В Е. Котова и В. К. Сабельфельда [36] по теории программирования, М. Хехта [55] и В. Н. Касьянова [25] по анализу программ, А. Ахо и Дж. Ульмана[4]. Г И. Бабецкого и др. [3], В. Н. Касьянова [27]. В. Н. Касьянова и И. В. Поттосина [31] по оп- тимизирующей трансляции, Н. Вирта [9], В. И Касьянова и В. К. Сабельфельда [32] и В. Н. Касьянова [30] по обучению программированию, Ф. Л. Бауэра и Г. Гооза [7] по основам информатики и др. Изложению теоретико-графовых методов, применяемых в программирова- нии, были посвящены книги А. Ахо и Дж. Ульмана [4], Д. Кнута [33], С. Гудмана и С. Хидетниеми [10], В. А. Евстигнеева [14—15], В. Липского [40], В. Н. Касьянова [28], М. Гэри и Д. Джонсона [11], Ю. Нивсргельта, Дж. Фаррара и Э. Рейнгольда [43], Т Кормена, Ч. Лейзерсона и Р Ривеста [34] и др. Определенный вклад в проблематику применения теории графов в программировании внесли работы авторов по средствам поддержки графов в программировании и созданию "энциклопе- дии" по алгоритмам на графах для программиста [29]. Эта "энциклопедия" строилась на основе группировки алгоритмов и соответствующих задач информатики вокруг важнейших классов графов, а также путем выделения в отдельную книгу толкового словаря по теории графов. В процессе работы над энциклопедией был выпущен ряд книг, важнейшими из которых явля- ются "Теория графов алгоритмы обработки деревьев" [17], "Теория графов: алгоритмы обра- ботки бесконтурных графов" [18], "Сводимые графы и граф-модели в программировании" [19], а также "Толковый словарь по теории графов в информатике и программировании" [20]. Сде- лан первый шаг в издании "энциклопедии" на английском языке [56]. Отметим также, что разделы по хордальным графам и методам распознавания графов и оты- скания потоков в сетях написаны по материалам обзоров 116, 57]; к ним мы отсылаем читателя за соответствующими ссылками на литературу.
58 Часть I. Обработка и визуализация графов Список литературы 1. Адельсон-Вельский Г. М.. Диниц Е. А., Карзанов А. В. Потоковые алгоритмы. — М.: Нау- ка, 1975. 2. Алгоритмы и программы решения задач на графах и сетях/ М. И. Нечепурепко, В. К. Попков, С. М. Майнагашев и др. — Новосибирск: Наука, 1990. 3. АЛЬФА— система автоматизации программирования / Г. И. Бабецкий и др.— Новоси- бирск, Наука, 1967 4. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции.— М.: Мир, 1978. —Т. 1, 2. 5. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. — М.. Мир, 1979. 6. Басакер Р., Сааз и Т. Конечные графы и сети. — М.. Наука, 1974. 7 Бауэр Ф. Л., Гооз Г. Информатика. -— М: Мир, 1990. — Т. 1,2. 8. Берж К. Теория графов и ее применения. — М.: Изд-во иностр, лит., 1962. 9. Вирт Н. Алгоритмы + структуры данных = программы. — М.. Мир, 1985. 10. Гудман С., Хидетниеми С. Введение в разработку и анализ программ. — М.: Мир, 1981. 11. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые задачи.— М.: Мир, 1982. 12. Дискретная математика и матемаз ические вопросы кибернетики / Под общ. ред. С. В. Яб- лонского, О. Б ЛуПанова. — М Наука, 1974 —Т. 1. 13. Дистель Р. Теория графов. -— Новосибирск: Изд-во ИМ СО РАН, 2002. 14. Евстигнеев В. А. Теория графов и программирование. — Новосибирск: Изд-во НГУ, 1978. 15. Евстигнеев В. А. Применение теории графов в программировании. — М.: Наука, 1985. 16. Евстигнеев В. А. Хордальные графы и их свойства // Проблемы систем информатики и программирования / Под ред. В. Н. Касьянова. — Новосибирск: ИСИ СО РАН, 1999. — С. 33—63. 17 Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки деревьев. — Ново- сибирск: Наука, 1994 18. Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки бесконтурных гра- фов. — Новосибирск: Наука, 1998. 19. Евстигнеев В. А., Касьянов В. Н. Сводимые графы и граф-модели в программировании. — Новосибирск: Изд-во ИДМИ, 1999. 20. Евстигнеев В А., Касьянов В. Н. Толковый словарь по теории графов в информатике и программировании. — Новосибирск: Наука, 1999. 21. Ершов А. П. Введение в теоретическое программирование. Беседы о методе. — М.. Наука, 1977 22. Зыков А. А. Теория конечных графов. 1. — Новосибирск: Наука, 1969. 23. Зыков А. А. Основы теории графов — М.. Наука, 1987 24 Исследования по прикладной теории графов / Под ред. А. С. Алексеева. — Новосибирск' Наука, 1986.
Глава 1. Графы и сети 59 25. Касьянов В. Н. Методы анализа программ. — Новосибирск: Изд-во НГУ, 1982 26. Касьянов В. Н. Введение в теорию оптимизации программ. Оптимизирующие преобразо- вания программ и их обоснование. — Новосибирск: Изд-во ВЦ СО АН СССР, 1985. 27 Касьянов В Н. Оптимизирующие преобразования программ. — М.: Наука, 1988. 28. Касьянов В. Н. Лекции по теории формальных языков, автоматов и сложности вычисле- ний. — Новосибирск: Изд-во НГУ, 1995. 29. Касьянов В. Н. Применение графов в программировании // Программирование. — 2001, №3, —С 51—70. 30 Касьянов В. Н. Курс программирования на Паскале в заданиях и упражнениях — Ново- сибирск, Изд-во НГУ, 2001. 31. Касьянов В. Н., Поттосин И. В. Методы построения трансляторов. — Новосибирск: Нау- ка. 1986. 32 Касьянов В. Н., Сабельфельд В. К. Сборник заданий по практикуму на ЭВМ. — М.: Нау- ка. 1986 33. Кнут Д. Искусство программирования для ЭВМ. — М.: Мир. 1976. — Т. 1, 1977. — Т. 2; 1978 —Т. 3. 34. Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ.— М.: МЦНМО, 1999. 35 Котов В Е. Введение в теорию схем программ. — Новосибирск: Наука, 1978. 36. Котов В. Е., Сабельфельд В. К. Теория схем программ. — М.: Наука, 1991. 37 Кристофидес Н. Теория графов. Алгоритмический подход. — М.: Мир, 1978. 38. Лавров С. С. Программирование. Математические основы, средства, теоремы.— СПб.: БХВ-Петербург, 2001. 39. Лекции по теории графов / В. А. Емеличев, О И Мельников, В. И. Сарванов, Р И. Тыш- кевич. — М.: Наука. 1990. 40. Липский В. Комбинаторика для программистов. — М.: Мир, 1988. 41. Майника Э. Алгоритмы оптимизации на сетях и графах. — М.: Мир, 1981. 42. Миркин Б. Г., Родин С. Н. Графы и гены. — М.. Наука, 1977. 43. Нивергельт Ю., Фаррар Дж , Рейнгольд Э. Машинный подход к решению математических задач. — М . Мир, 1977. 44. Оре О. Теория графов. — М.: Наука, 1968. 45. Пападимитриу X., Стайглиц К. Комбинаторная оптимизация. Алгоритмы и сложность. — М.. Мир, 1985. 46 Применение теории графов в химии. — Новосибирск: Наука, 1987 47 Свами М., Тхуласираман К. Графы, сети и алгоритмы. — М Мир, 1984. 48. Сешу С., Рид М. Б. Линейные графы и электрические цепи. — М.: Высш, шк., 1971. 49. Татт У Теория графов— М.: Мир, 1988. 50 Уилсон Р Введение в теорию графов. — М.. Мир, 1988. 51. Форд Л., Фалкерсон В. Потоки в сетях. — М.. Мир, 1966. 52. Харари Ф. Теория графов. — М.: Мир, 1973.
60 Часть I. Обработка и визуализация графов 53. Di Battista G., Eades P., Tamassia R., Tollis l.G. Graph Drawing: Algorithms for Vizualization of Graphs. — Prentice Hall, 1999. 54. Drawing Graphs. Methods and Models / Ed. M. Kaufmann, D. Wagher. — Berlin: Springer. 2001. — (Leet. Notes Comput. Sci.; 2025). 55. Hecht M.S. Flow analysis of computer programs. — New York: Elsevier. 1977. 56. Kasyanov V.N., Evstigneev V.A. Graph Theory for Programmers: Algorithms for Processing Trees. — Kluwer Acad. Publ., 2000. 57 Van Leeuwen J. Graph algorithms. Handbook of Theoretical Computer Science / Ed. J. van Leeuwen. — Elsevier Sci. Publ., 1990. — Vol. A. — P. 523—611.
ГЛАВА 2 Ориентированные деревья С точки зрения классической теории графов, деревья— мало привлекательный объ- ект, в монографиях по теории графов им редко отводится больше одной главы. Иное отношение к деревьям в прикладной теории графов: они играют важную роль в про- граммировании, теории информационных систем, электротехнике, химии и пр. Класс алгоритмов на деревьях образует один из наиболее важных и широко исполь- зуемых в программировании классов алгоритмов теории графов. Эти алгоритмы по своей фундаментальности для задач обработки информации можно сравнить только с алгоритмами вычисления функций анализа или алгоритмами линейной алгебры в вычислительной математике. 2.1. Ордеревья и их свойства Опираясь на понятие дерева, которое было введено в гл. 1, рассмотрим классы де- ревьев, наиболее используемые в программировании и информатике. 2.1.1. Корневые деревья Дерево называется корневым, если в нем выделена вершина г, именуемая корнем. Некорневое дерево иногда называют свободным. При решении отдельных задач, на- пример при установлении изоморфизма деревьев, в качестве корня удобно выбирать одну из центральных вершин. Ориентированным деревом с корнем г (или древесностью с корнем г) называется корневое дерево, в котором каждое ребро заменено дугой, таким образом, что либо из каждой вершины можно попасть в корень, двигаясь вдоль ориентации дуг (входя- щее дерево), либо в каждую вершину можно попасть из корня, двигаясь вдоль ориен- тации дуг (выходящее дерево). Во входящем ориентированном дереве корень дости- жим из каждой вершины, в выходящем — каждая вершина достижима из корня (рис. 2 I). Ориентированное дерево кратко называют ордеревом. Нетрудно увидеть, что задание корня превращает дерево в ордерево В выходящем ордереве в точности одна вершина (корень) имеет нулевую полустепень захода,
62 Часть I. Обработка и визуализация графов у всех остальных вершин полустепень захода равна единице. Висячие вершины вы- ходящего дерева называются листьями Выходящее ордерево иногда называют растущим. Рис. 2.1. Корневое входящее и выходящее деревья Пусть Т(Х, U) есть ордерево с корнем г. Расстояние d(x,y) между вершинами х и у есть число дуг в пути, ведущим из х в у. Если такого пули нет, то полагают d(x,y) = оо. Говорят, что вершины ордерева образуют k-й ярус или расположены на к-м уровне, если их расстояние от корня равно к. Наибольшее к, при котором к-й ярус не пуст, называется высотой растущего ордерева. Всякая вершина растущего орде- рева может рассматриваться как корень растущего из нее поддерева. Очевидно, что для такого поддерева высота определяется аналогично. При изображении ордерева на плоскости все вершины одного уровня располагаются на одной прямой так, чтобы дуги ордерева не пересекались, и для каждой вершины на к-м уровне можно было бы указать ее братьев и соседей. Вершины х иу называются соседями, если они распола- гаются рядом на их уровне, и братьями, если они имеют общего предка — вершину на предыдущем уровне, из которой идут дуги в вершины хну (рис. 2.2). Длину пути из корня в некоторую вершину часто называют глубиной вершины. Дере- во именуется выровненным, если его листья располагаются на одном уровне. Выходящее ордерево называется упорядоченным, если у него упорядочены множест- ва выходящих из каждой вершины дуг. Два изоморфных ордерева могут не быть изоморфными, если их рассматривать как упорядоченные с разными упорядочениями выходящих дуг (рис. 2.3). Упорядоченные деревья иначе называют плоскими.
Гпава 2. Ориентированные деревья 63 Метрическими свойствами деревьев называются свойства, определяемые метрикой деревьев, т. е. расстояниями между его вершинами. Метрические свойства, связан- ные с центром дерева, рассмотрены в гл. I. К другим метрическим свойствам отно- сятся следующие: А. Система расстояний между висячими вершинами дерева определяет дерево однозначно с точностью до изоморфизма. Б. Реализация метрики с помощью дерева является наиболее экономной в следующем смысле: если метрику р, заданную на множестве X, можно реализовать деревом Т=(Ут, Е/), то для всякого графа G = (Кд, Е(;), реализующего ту же метрику, имеем \Vc\>\VT\,\EG\>\Er\. 1-й ярус 2-й ярус 3-й ярус 4-й ярус 5-й ярус 6-й ярус Рис. 2.2. Соседи и братья вершин ордерева Рис. 2.3. Упорядоченные деревья
64 Часть I. Обработка и визуализация графов Рассмотрим основные операции над упорядоченными деревьями. Операция подклеивания П(1\, Т2, Т3). Трем деревьям 7\, Т2, Т2 таким, что Т2 есть под- дерево дерева 7\, ставится в соответствие дерево П(1\, Т2, 7\), получаемое из Tt при- соединением 7з к корню г(Т2\ при этом Т3 становится левым сыном корня г(7г) (рис. 2.4). Рис. 2.4. Операция подклеивания Операция перестановки поддеревьев ПР(7\, Т2, Т3). Пусть г(Т^) и г(Т2) суть сыновья одной вершины в дереве 7), результат операции представлен рис. 2.5 Рис. 2.5. Операция перестановки поддеревьев Операция отделения поддерева О(7\, Т2). Результатом операции является дерево О(Т\, Т2), получаемое из 7) выбрасыванием поддерева, корень которого совпадает с корнем дерева Т2 (рис. 2.6). Операция выделения самого левого поддерева ВЛП(Т). Операция выделения правого брата ВПБ(7\, Т2). Под выделением правого брата по- нимается операция, выделяющая в 7\ поддерево, корнем которого является правый брат корня г(Г2). Операция выделения корня ВК(Т). Введем следующие обозначения: П А~* — обращение бинарного отношения А с А*А\ □ А — транзитивное замыкание бинарного отношения;
Гпава 2. Ориентированные деревья 65 О В — рефлексивно-транзитивное замыкание бинарного отношения А: В=Аи {(а, а) | а е А}; □ Л(В)— срез бинарного отношения А через множество В, т. е. А (В~) = {с | 3 b е В, (Ь, с) еА} Для удобства вместо Л({а}) часто пишут Л(а); П рг| А - - проекция бинарного отношения А по первой компоненте: prt А = {а | 3 Ь, (а, Ь)е А} Будем считать (а, 0) = 0, (0, £>) = 0, (0, 0) = 0. Рис. 2.6. Операция отделения поддерева Ориентированным деревом называется пара <Ai, Л.>, где Л( — конечное множество вершин, aAtcAt х А। удовлетворяет свойствам для всех а, Ь, с е А 1 |ЛГ'(а)|£ 1 ла f? At(a). 2 . (лДа) | < 1 л |л/(с)| = 0 => b = с. Свойство 1 отражает тот факт, что в вершину входит не более одной дуги и нет цик- лов; свойство 2 является условием единственности корня. Имеет место следующий факт. В. Если <АЬ Ai>— ориентированное дерево, то <At, At>— абстрактная полуре- шетка. Упорядоченным деревом называется тройка <At, Л(, Л2>, где <At,At>— ориентиро- ванное дерево, а Лг с А ( * А । удовлетворяет свойствам: 1. иЕАг(а) 2. |Л2(д)|<1 3. |М«)|<1. 4. Л2(а) и Л,' = А ,(Л J '(а)). Отношение Л2, удовлетворяющее свойствам I—4, задает линейный порядок на мно- жестве сыновей каждой вершины. Заметим, что если <Л1,Л1, Л2>— упорядоченное дерево, то множество Л \Л, (Л) со- стоит в точности из одного элемента, называемого корнем дерева. 3 Зак. 202
66 Часть I. Обработка и визуализация графов Пусть Т, = <А|, А|, Л2>, i = 1, 2, 3,— упорядоченные деревья, k, = А, \ А\ (А,). Т4 = Щ7\, Т2, Т3). Если А2 с А' и А' о А3 = 0, то Л4 = А' и/, А*=А3 иЛ.и^хУ А2 = А 2 u А J и к3 х (A J (А2) \ А\ (А [ (А2))), иначе операция не определена. Г4 = ПР(7], Т2, Т3). Если А2 с А1 и к3 с А', то л4 = л*,л4=л;, А^А^СА'у'С^хк2^ А2х Л ‘ (A2) ((Л2)"'(А3) х к3и к3 х А2 (к3)) U (А^'Ск2) х k3u о к3 х а\ (А2) о (Л2)“'(А3) и А2 х л ‘ (А3), иначе операция не определена. Т3 = О(7\, Т2), А3 = А'\ А3 (А2), А’ = Л J \ Л2хЛ2, А2 = А2\ А2хА2. Т2 = ВЛЩ7\\ А2 =А\ (л](А2) \ А\ (ЛJ (А1))), А2= А' п А2хА2,А2 = А2 пА2хА2 Т= ВПБ(1\, Т2), А3 =а\ (А2 (к2)), А3-А, Г> А3хА3, А2 = а\ П А3хА3. Т2 = ВК(Т\\ Л2 = А', Л,=0, Л2 = 0. Система операций на множестве упорядоченных деревьев Л называется с-полной, если для любого Т с. А, Т = {7]}, i е 7, такого, что о А' = А, с помощью этих one- /е/ раций можно построить любое дерево Т' = <А (, Л (, Л2>, А' с. А. Имеют место следующие утверждения: Г. Система операций {П, О, ВЛП, ВПБ, В К} с-полна на множестве всех упорядочен- ных деревьев. Д. Система операций {П, ПР, О, ВЛП, ВПБ, ВК} функционально независима. 2.1.2. Бинарные деревья Ордерево называется бинарным, если оно определяется следующим рекурсивным образом: □ одновершинное дерево есть бинарное дерево; □ тройка (7/, г, Тг) есть бинарное дерево с корнем г, левым поддеревом 7} и правым поддеревом Тг, причем как 7}, так и Тг суть бинарные деревья, возможно, пустые (рис. 2.7). Из этого определения вытекает, что для каждой дуги, выходящей из любой вершины бинарного дерева, указывается, правая она или левая. От упорядоченного дерева би- нарное дерево отличается тем, что если из вершины выходит только одна дуга, то обязательно указывается, правая она или левая (рис. 2.8).
Глава 2. Ориентированные деревья 67 Рис. 2.8. Два разных бинарных дерева Бинарные деревья называются также двоично-поисковыми. Некоторые авторы ис- пользуют термин "бинарное дерево" для обозначения упорядоченного дерева, у кото- рого из каждой вершины выходят либо две дуги, либо ни одной, и термин "двоично- поисковые деревья" для обозначения бинарных в нашем смысле деревьев. Обобщением бинарных деревьев являются m-арные деревья, в которых каждая вер- шина является корнем не более чем т поддеревьев, каждое из которых в свою оче- редь есть m-арное дерево, возможно, пустое. Левостороннее бинарное дерево определяется рекурсивно следующим образом: П одновершинное дерево есть левостороннее бинарное дерево; □ бинарное дерево, в котором правое поддерево является пустым, а левое — лево- сторонним бинарным деревом, есть левостороннее бинарное дерево. Аналогичным образом определяется правостороннее бинарное дерево. 2.1.3. Представление деревьев Представлением дерева называется способ записи информации о нем, однозначно и полностью восстанавливающий структуру дерева и позволяющий вычислять его ха- рактеристики. Выбор представления зависит от решаемой задачи и способа (ручной, машинный) ее решения. Способы представления деревьев делятся на общие — для всех графов представления, и специфические — для деревьев.
68 Часть I. Обработка и визуализация графов Представление с помощью матрицы смежности Это представление является общим для всех графов; оно определяет граф однозначно с точностью до изоморфизма, но является довольно неэкономным, т. к. ненулевыми являются для и-вершинного дерева только 2л—2 из и2 элементов матрицы. Матрица смежности есть квадратная матрица А размером л х и, у которой элемент а,7 определяется следующим образом: Г1, если вершины х, и х/ смежны, [О — в противном случае. Для неориентированного графа матрица смежности симметрична относительно глав- ной диагонали, поэтому можно задавать только верхнюю треугольную половину матрицы, но это не улучшает ситуацию. Другим недостатком этого представления является тот факт, что трудоемкость алгоритмов, работающих с таким представлени- ем, не может быть ниже О(л2). Например, дерево, изображенное на рис. 2.9, может быть представлено в виде матрицы 00010 0- 000 000100 000 00010 0- 000 111 0 10 0 0 0 0 0 0 1 0 1 1 0 0 000010 000 0 0 0 0 10 0 1 1 000000 100 000000 100 Рис. 2.9. Дерево Достоинство же этого представления — легкость получения, а также возможность использования его для языков, допускающих побитовую обработку двоичных после- довательностей, рассматриваемых как одно слово. Представление с помощью матрицы инцидентности — также общее для всех графов представление; оно еще более неэкономно и нами не рассматривается. Представление с помощью списков смежности В этом представлении каждой вершине дерева сопоставляется список смежных вер- шин вида:
Гпава 2. Ориентированные деревья 69 Для дерева Т(см. рис. 2.9) списки смежности могут иметь следующий вид: 4: 1,2,3, 5; 3:4, 6, 7; 7: 5, 8, 9; 1.4; 2:4; 3:4; 6:5; 8:7; 9:7 Понятно, что представление дерева в виде списков смежных вершин не однозначно и задает порядок на множествах смежных вершин. По существу каждое такое пред- ставление дерева опирается на ту или иную его реализацию в виде упорядоченного дерева. Разные реализации указанных списков смежности позволяют получать различные представления деревьев. Например, при реализации списков с помощью массива можно отводить под соседние элементы списка соседние элементы массива (так на- зываемое последовательное распределение), но в этом случае не всегда эффективно реализуются операции по модификации графа. Другой подход — это использование так называемого связанного представления спи- сков В этом случае список представляет собой совокупность структурных объектов (записей), каждый из которых содержит управляющую и собственно информацион- ные части. Управляющая часть обязательно содержит информацию об адресе сле- дующего элемента списка (или его отсутствии— в случае последнего элемента). В простейшем случае это просто указатель, который хранит ссылку на следующий элемент списка, если такой есть, или пустую ссылку, если элемент является послед- ним в списке. Список может быть односторонним (односвязным), если управляющая часть ограни- чивается указанием (ссылкой) на следующий элемент, и двусторонним (двусвязан- ным), если в управляющей части содержится также ссылка на предыдущий элемент. В дополнение к указанным свойствам список может быть циклическим, если конеч- ный элемент по управляющей информации считается предшественником начального элемента. Возможны любые комбинации указанных свойств — список может быть циклическим и простым или симметричным. Для ориентированных деревьев возможно задание с помощью двух семейств списков смежности: один содержит вершины, достижимые из данной вершины (сыновей), другой — вершину предка (отца). Упорядоченное ориентированное дерево удобно реализовывать в виде бинарного дерева с тем же множеством вершин. В бинарном дереве, представляющем ордерево, у каждой вершины имеется не более двух сыновей: левый сын — это старший сын в ордереве, если он есть, а правый сын — это брат данной вершины в ордереве, если он есть. Таким образом, для представления бинарного дерева можно использовать сово-
70 Часть I. Обработка и визуализация графов купность записей по числу вершин, каждая из которых состоит из информационной части и двух указателей, хранящих ссылки на корни левого и правого поддеревьев. Рассмотрим следующие примеры. Представление дерева Т (рис. 2.10) с помощью списков при использовании двухком- понентных звеньев (записей), в которых в первом поле находится либо указатель, либо метка вершины, а во втором — всегда указатель, изображено на рис 2.11. Рис. 2.10. Дерево Т Рис. 2.11. Представление дерева Т с помощью списков Представление того же дерева Т с помощью двусторонних списков, аналогичное представлению на рис. 2.11, но с петлями и контурами указателей, благодаря чему достигается двусторонность, изображено на рис. 2.12. Представление дерева с помощью односторонних списков с использованием звеньев одинакового размера (одно поле для данных и три поля указателей в каждом слове) имеет вид, изображенный на рис. 2.13.
Глава 2. Ориентированные деревья 71 Рис. 2.12. Представление дерева Т с помощью двусторонних списков Рис. 2.13. Представление дерева Т с помощью односторонних списков Представление дерева с помощью двусторонних списков с использованием звеньев переменного размера, снабженных счетчиками, в которых задается количество указа- телей в данном звене, изображено на рис. 2.14. Представление деревьев как графов данных Граф данных получается из структуры данных, если отвлечься от элементарных данных, которые соответствуют вершинам структуры, и сосредоточиться на связях между ними. Пусть С= {с}— множество ячеек дрнных. На практике это множество всегда ко- нечно, но мы будем предполагать, что оно счетно. Пусть далее Л есть конечное
72 Часть I Обработка и визуализация графов Рис. 2.14. Представление дерева Т с помощью двусторонних списков и звеньев переменного размера множество частичных преобразований на С, называемых преобразованиями типа, и Л'— моноид, порождаемый преобразованиями из Л с помощью операции компози- ции преобразований. Будем считать, что для каждой пары ячеек с, d е С существует преобразование Е, е Л такое, что Е,(с) = d. Определим теперь граф данных Г = (С, Л) как орграф, у которого множеством вер- шин является множество С и между вершинами cud имеется дуга (с, d), если суще- ствует преобразование Е, е Л такое, что d= ^(с). Ясно, что существование преобразования Е, е Д', переводящего ячейку с в d, соответ- ствует наличию пути из вершины с в вершину d, а существование для каждой пары ячеек соответствующего преобразования в Л' равносильно утверждению о том, что граф данных всегда сильно связен. Рассмотрим следующие примеры. Бинарное дерево Т (рис. 2.15). Вершины дерева занумерованы числами 1,2,3, ..., а три типа связей представлены следующими преобразованиями над множеством N натуральных чисел: п/п) = правый потомок (и) = 2п; О/(н) = левый потомок (и) = 2п + 1, л(л) = предок (л) = [л/2]. Преобразование "предок" -— единственное, которое определено не для всех вершин. Факт, что л(1) = [1/2] = 0 g N означает, что ячейка с номером 1 (корень дерева) не имеет предка. Бинарное дерево 7°’ (рис. 2.16) отличается от бинарного дерева Т тем, что преобра- зование "предок" заменено преобразованием со(и) = 1.
Глава 2. Ориентированные деревья 73 Рис. 2.15. Бинарное дерево Т Рис. 2.16. Бинарное дерево Т'1’ Рис. 2.17. Бинарное дерево с мостами
74 Часть I. Обработка и визуализация графов Бинарное дерево Гп2 с мостами (рис. 2.17). Множество вершин есть множество нату- ральных чисел N, множество преобразований Л есть множество {оу, о>, л, 0r, 0J, где о,(и) = 2п, О/(и) = 2п + 1, л(и) = [п/2], Р,(л) = л + 1, если п = 4/и (jn> 1); 0/(и) = л + 1, если п = 4m + 2(m > 1). Вариант бинарного дерева (рис. 2.18). Множество вершин есть множество {0} u N, множество преобразований Л есть множество {ст/, ст,, л}, где ст/л) - 2п + 1, ст,(и) = 2 и, п 0, л(и) = [п/2],п*0. Рис. 2.18. Вариант бинарного дерева Представление с помощью списка ребер и кода Прюфера Дерево при этом способе задается перечислением пар <v„ vj> или троек <v„ у,, н/>, если дополнительно нужна нумерация ребер. Характер связей в списке определяется исходя из условий задачи. Например, для дерева Т(см. рис. 2.7) имеем Т= {<1, 4>, <2, 4>, <3, 4>, <4, 5>, <5, 6>, <5, 7>, <7, 8>, <7, 9>}. Пусть Т— дерево с множеством вершин {vb v2,..., v„}. Будем считать, что номер вершины vt равен i. Сопоставим дереву Т последовательность [аь а2, ..., л„-2], назы- ваемую кодом Прюфера, по следующему правилу: функ КОД_ПРЮФЕРА(7 дерево) = 1 Пусть л — число вершин в Г, а А — целочисленный вектор длины л - 2;
Глава 2. Ориентированные деревья 75 2. В := [1 л], 3 для / от 1 до п - 1 цикл 4. b = min{fc е В; к — номер висячей вершины}; 5. А[г] := номер вершины, смежной вершине с номером Ь, 6. В = В - {Ь}; 7 Удалить из Т вершину с номером А[/] все; 8. возврат А все Рассмотрим следующий пример. Для дерева Т (рис. 2.19) код Прюфера имеет вид: Р£Г)=[2,5, 5, 5, 6, 6, 10, 9, 10, 11, 13, 15, 15, 10, 13, 13, 13]. Распаковка кода Прюфера осуществляется следующим способом: функ РАСПАКОВКА (А: код) = 1 Пусть Тсостоит из вершин {Vi, Vz, ..., ип} таких, что номер вершины V, равен /, где п — длина кода А плюс 2; 2 В = [1 л] 3 для / от 1 до п + 1 цикл 4 . Ь •= min {к е В к* А[/1 для любого j> /}; 5 ВТ добавить ребро, соединяющее вершины с номерами b и Ар], 6 . В=В - {Ь} все; 7 возврат Т все
76 Часть I. Обработка и визуализация графов В случае корневого ордерева процедуры построения кода Прюфера и его распаковки аналогичны. Необходимо только на последнем месте в А указывать корневую верши- ну и при распаковке кода А исключать номер этой вершины из множества В. Операции над деревьями и кодами Прюфера Будем считать, что вершины двух разных деревьев нумеруются различными числами, причем номера одного дерева всегда больше или меньше любого номера другого. Это требование часто выполняется в практических реализациях, т. к. для вершин каждого дерева обычно отводят последовательные массивы номеров ячеек памяти. Если все номера дерева Тх (или ориентированного дерева Тх) меньше всех номеров дерева Т2 (или Т2), то пишут Тх < Т2 (или Тх < Т2). Рассмотрим следующие операции над деревьями: a ф — операция замены номера а вершины Т на номер Л; ь о a-^b — операция склеивания двух деревьев по вершинам а и Ь, т. е. дерево о Тха —>ЬТ2 получается из Т2 и7] отождествлением вершин а из Тх и b из Т2 и при- своением склеенной вершине номера b (при склеивании ордеревьев добавляется тре- бование, чтобы вершина b была корневой). о На рис. 2.22 представлен результат выполнения операции 7] 3 —> 10 Т2, где 7] и Т2 —деревья, изображенные на рис. 2.20 и 2.21. Рассмотрим некоторые операции над кодами Прюфера: [ ] — операция формального отбрасывания квадратных скобок; определена на всех выражениях вида [яь а2,..., а„], b, [Z>|, b2,Л,„] и состоит в отбрасывании всех внут- ренних квадратных скобок и добавлении двух внешних; с — операция вставки кода Прюфера; если Л>( Тх) = [а,, а2,ак, с, ак+2,а„_х] и среди чисел ак+2, ак+2,..., а„-х нет числа с, то Р2(Тх) с P2(f2) = [tri, а2,..., ак, Р2{Т2), с, ак+2,..., «„.J. Справедливы следующие соотношения, связывающие операции над деревьями и ко- дами Прюфера: если Тх < Т2, то 0 « Р2 (Тха->ЬТ2 ) = [Р2 (} Тх), Ь, Р2 (Т2)]; ь
Глава 2. Ориентированные деревья 77 Рис. 2.21. Дерево f2 Рис. 2.22. Дерево Т\ 3 —> 10 f2 о если Т\ > Т2, то необходимо рассматривать дерево 7\b —> аТ2, и все сводится к пре- дыдущему случаю; если 7\>Т2, то _ ° _ а Р2(7\а^ЬТ2) = [ Р2) с, Р2(Т2) ], Л где с— непосредственный предок вершины а в дереве 7\; если f, > Т2, то _ 0 а p2(7’Ifl^z,7’2)=[p2(f2),p2afI)]. ь Оптимальное кодирование деревьев ОО Пусть Л = А„ А, — конечное множество. Предположим, что при каком-то способе /=| кодирования элементов из А для запоминания одного элемента из А, используют са- мое большееj(z) битов памяти.
78 Часть I. Обработка и визуализация графов Кодирование/(/) называется оптимальным, если где //(/) = log21 А, | и | А, | — число элементов в А,. При задании дерева списками смежности и при условии, что вершины помечены числами Л'’ + 1, N + 2,Л' + п, имеет место соотношение lim 2W = )im (3»-2)log 2(^+H) = 3> Л-м» Н (и) п->со Н(п) т. к. списки смежности содержат (Зя - 2) номеров вершин и каждый номер требует log2(W + я) битов. При задании ордерева списками смежности j(n) = (2п - 1) logsfA^ + и), что дает Пт-Ж = 2. П-КО Н(п) Таким образом, представление деревьев списками смежности с указанной точки зре- ния неоптимально. Оптимальным же является кодирование деревьев кодами Прюфе- ра, т. к. для хранения кода Прюфера необходимо ./(я) = (я - 2) log/W + я) битов памяти, поэтому lim — П— = 1. П-»ео Н(п) Кодирование деревьев с помощью обхода вершин Пусть дан некоторый порядок прохождения вершин. Линейным кодом к(Т) дерева Т называется слово в некотором алфавите, сформированное согласно заданному поряд- ку прохождения вершин и составленное по определенному правилу из количествен- ных характеристик и признаков вершин, а также ограничителей. При представлении деревьев линейными кодами предполагается, что дерево распо- ложено на плоскости без пересечения ребер, так что, двигаясь от корня, можно в каж- дой вершине говорить о левом, правом, самом левом, самом правом и т. д. ребре. Для удобства считаем, что дерево изображено на плоскости в виде выходящего дерева (см. рис. 2.1). Зафиксируем следующий порядок обхода вершин (вариант поиска в глубину): начиная с корня v0, выбираем самое левое инцидентное ему ребро, двигаясь по нему к следующей вершине, если она не висячая, снова выбираем самое левое ребро, и так до тех пор, пока не попадем в висячую вершину. Потом возвращаемся
Глава 2. Ориентированные деревья 79 назад к первой такой вершине, которой инцидентны еще не пройденные ребра, выби- раем из них самое левое и движемся до следующей висячей вершины. Обход закан- чивается в корне, когда будут пройдены все вершины. Коды с дублированием характеристик вершин Используются следующие способы построения разных линейных кодов, в которых могут повторяться составляющие их элементы. 1. В качестве кода дерева берется перечень вершин, начиная с корня; в коде дерева каждая вершина встречается столько раз, сколько она проходится во время обхо- да, в частности, каждая висячая вершина входит в код ровно один раз. Например, для дерева (рис. 2.23) мы получаем код к(Т) = V0, Vi, V2, Vh V3, V4, V3, V,, V5, V|, V0, V6, V7, V6, V8, V9, V(0, v8, v6, v0. 2. В качестве кода рассматривается перечень всех путей от корня к висячим верши- нам в порядке их прохождения при обходе дерева. Например, для дерева Т (см. рис. 2.23) мы получаем код КТ) = v0, vb v2, Vo, vb v3, v4, v0, v5, v0, v6, v7, v0, v8, v9, v0, v8, v6, V,o 3. В качестве кода берется перечень вершин при обходе дерева, но в качестве харак- теристики вершины записывается ее расстояние от корня. Например, для дерева Т (рис. 2.24) мы получаем код к(Т) = 1,2, 1,2, 3,2, 1,2, 1,0, 1,2, 1,2, 3,2, 3, 2, 1. 4. В качестве кода берется перечень вершин, как при способе 3, но вместо каждой монотонно возрастающей или убывающей последовательности записываются лишь ее крайние значения. Например, для дерева (см. рис. 2.24) мы получаем код Л(7) = 2, 1,3, 1,2, 0, 2,3, 2,3, 1. 5. В качестве кода рассматривается 0—1-последовательность, получаемая из кода при способе 3, если при переходе от одной вершине к другой писать " 1" при уве-
80 Часть I. Обработка и визуализация графов личении расстояния от корня на единицу, и "О" — при уменьшении. Например, для дерева Т (рис. 2.25) мы получаем код k(T) = 110110100011010110101000. Код, получаемый способом 5, является оптимальным по длине (в битах) среди всех возможных кодов корневых упорядоченных деревьев. Рис. 2.24. Дерево Т Рис. 2.25. Дерево Т Коды, свободные от повторений Существует три способа линейного кодирования деревьев, при которых характери- стики вершин в кодах не повторяются. 1. В качестве кода берется последовательность полустепеней исхода вершин, выпи- сываемых в порядке, в котором вершины встречаются при обходе, с одним огра- ничением: при обратном движении по дереву полустепени исхода не повторяют- ся. Например, для дерева 7(рис. 2.26) мы получаем код к(Т) = 220200. Бинарные деревья при таком способе кодирования восстанавливаются неодно- значно. Рис. 2.26. Дерево Т 2. В качестве кода рассматривается последовательность расстояний вершин от корня (корень не кодируется). Для деревьев, у которых полустепени исхода вершин рав- ны 2 или 0, достаточно записывать расстояния от корня только для висячих вер-
Глава 2 Ориентированные деревья 81 шин. Бинарные деревья при таком кодировании восстанавливаются неоднозначно. Для дерева Т(см. рис. 2.26) данный код имеет вид к(Т) = 2, 3, 3, 1 3 В качестве кода берется последовательность числа вершин в поддереве с корнем в рассматриваемой в данный момент вершине. Для дерева Т, представленного на рис. 2 26, данный код имеет вид 4(7) = 7,5,1,3,1,1,1. Коды с использованием ограничителей Данные коды используют в качестве характеристик вершин такие величины, как вы- сота, порядковый номер среди братьев и др. При этом для устранения неоднозначно- сти восстановления по таким кодам структуры деревьев применяются ограничители. Рассмотрим два примера. 1. В качестве кода берется последовательность букв а и р, причем а помещается в последовательность, если при обходе встречается внутренняя вершина, а Р — если висячая вершина. Ограничитель (это —- закрывающая скобка) записывается в конце каждого поддерева. Для дерева Т, представленного на рис. 2.26, данный код имеет вид А(7) = аар) ар) р) р). 2. В качестве кода для бинарных деревьев берется последовательность чисел 0 и 1, при этом левым вершинам соответствует признак "1", а правым— "О"; при по- строении кода выписываются все пути из корня в листья, после каждого пути ста- вится ограничитель — закрывающая скобка. Для дерева Т(см. рис. 2.26) данный код имеет вид /?(7) = И) Ю1) 100)0). Уровневые коды корневых деревьев Пусть (7, z) обозначает корневое дерево с лежащим в его основе свободным деревом Т и корнем z. Уровень вершины v в (7, z)— это расстояние v от z плюс единица. Уровневый код (обозначение L(T, z) = [/,, Z2, •••> 4]) — это последовательность целых чисел, полученная выписыванием уровней вершин дерева (Г, z) в постфиксном по- рядке (см. разд. 2.2.12). Уровневый код называется каноническим (обозначение L*(T, z)), если он является наибольшим в лексикографическом упорядочении среди всех уровневых кодов, описывающих дерево. Например, для дерева Т, изображенного на рис. 2.27, имеем ЦТ, z) = [3,3,2,3,4,4,3,2,2,1], L\T, z) = [4,4,3,3,2,3,3,2,2,1]. Вершина z называется основным корнем свободного дерева Т (обозначение z (7) или просто z), если либо z — единственный центр Т, либо z — один из центров Z| и z2 би- центрального дерева 7, определяемый по следующим правилам. Пусть 7] и 72 — поддеревья, получаемые из 7 удалением ребра, соединяющего z, и z2. В качестве z
82 Часть I. Обработка и визуализация графов берется Z|, если 7) имеет меньше вершин, чем Т2, либо если 7) р Тг состоят из равного числа вершин, но L\l\, Z|) лексикографически предшествует последовательности L\T2, z2); в остальных случаях в качестве z берется z2. Уровневый код ЦТ, z) назы- вается главным уровневым кодом дерева Т. a L\T, z)— главным каноническим уровневым кодом дерева Т. Ротационный код бинарных деревьев Рассматриваются два вида преобразований бинарных деревьев в бинарные деревья: правая и левая ротации. Рис. 2.29 изображает результат правой ротации в вершине В дерева, изображенного на рис. 2.28, а рис. 2.28 — результат левой ротации в вершине А дерева с рис. 2.29. При этом любое (или все) из поддеревьев а, ₽ и у могут быть пустыми. Левая (правая) ротации в вершине А дерева Т имеет глубину к, если к — порядковый номер вершины А на пути по дереву Т от его корня к самому левому листу. Пусть Т— некоторое бинарное дерево с п вершинами. Тогда последовательность (х„_|5 х„_2, ..., х2, Х|) называется ротационным кодом дерева Т, если для последова- тельности деревьев Т„, Тп~\, Т„_ъТ2, Ц, в которой Т\ = Т, Тп левостороннее дере- во, и для любого i дерево 7}+i получается из Т, применением х, левых ротаций глуби- ны i Например, (0, 1, 0, 2) — ротационный код дерева Т, изображенного на рис. 2.29. Для того чтобы получить дерево Т по его ротационному коду X = (х„_ь х„_2, .... х,), нужно выполнить следующую функцию: функДЕРЕВО(Х : код) = 1. Пусть Т — левостороннее л-дерево, где л — длина кода X плюс 1; 2. для к от л 1 до 1 шаг — 1 цикл
Глава 2. Ориентированные деревья 83 Рис. 2.28. Левая ротация дерева Рис. 2.29. Правая ротация дерева Рис. 2.30. Ротационный код дерева
84 Часть I. Обработка и визуализация графов 3. цикл Х]к] раз 4. Выполнить над Т левую ротацию глубины к все все; 5. возврат Т все Коды Закса Пусть дано бинарное или Л-арное дерево Ten вершинами такое, что каждая внутрен- няя вершина дерева помечена числом 1, а каждая висячая — числом 0. х-кодом Закса дерева Т называется последовательность пометок его вершин, пере- численных в инфиксном (см. разд. 2.2.12) порядке (рис. 2.31). z-кодом Закса дерева Т называется последовательность номеров единиц в х-коде де- рева Т, перечисленных в порядке их возрастания (см. рис. 2.31). у-кодом Закса дерева Т называется последовательность номеров нулей в х-коде дере- ва Т, перечисленных в порядке их возрастания (см. рис. 2.31). Коды Ли Пусть Т— бинарное дерево, каждая внутренняя вершина помечена числом 1, а каж- дая висячая — числом 0. u-кодом Ли дерева Т называется последовательность пометок вершин, написанных в порядке обхода его в ширину (рис. 2.32). p-кодом Ли дерева Т называется последовательность номеров единиц в и-коде дере- ва Т, перечисленных в порядке их возрастания (см. рис. 2.32).
Гпава 2. Ориентированные деревья 85 Псуровневый позиционный код Ли дерева Т высоты h (см. рис. 2.32) — это последова- тельность М = Mi, М2, .... Л//1-1, где М,— последовательность номеров внутренних вершин уровня /, перечисленных в порядке их возрастания. Код Гапта для 2-3-деревьев Последовательность чисел at, a2, ..., ak называется кодом Ганта 2-3-дерева Т с внут- ренними вершинами (ключами), если ее можно получить при обходе внутренних вершин дерева Т по уровням снизу вверх, начиная с самого нижнего и кончая корнем, путем выписывания количества сыновей вершин, составляющих каждый уровень, в порядке их расположения слева направо (рис. 2.33). (2. 2, 3. 2. 2. 2, 3. 2) Рис. 2.33. Код Гаптв Классификационная схема линейных кодов Классификационное дерево линейных кодов представлено на рис. 2.34 В соответст- вии с приведенной классификацией различаются восемь групп линейных кодов. Л-представление упорядоченных деревьев Пусть «|,..., а„ — натуральные числа; R-вектор определяется следующим образом: 1. Если К= (ц,), то V есть /?-вектор.
86 Часть I. Обработка и визуализация графов 2. Если К|,Va —7?-векторы, то (^-«„[К,],[ГО(]) также есть /?-вектор, где [ ] — операция формального отбрасывания круглых скобок. 3. Никакие векторы, кроме указанных в 1,2, не являются /^-векторами. Отображение ф множества упорядоченных деревьев во множество /?-векторов опре- деляется следующим образом: □ если дерево Тсостоит из одной вершины а, то ф(7) = («); □ если а — корень упорядоченного дерева Т и Тъ ], Тп — поддеревья Т, то ф(7) = («,-«, [ф(7',)Ь [ф(7„)]). Использование количественной характеристики Повторное вхождение символов Наличие ограничителей Рис. 2.34. Классификация кодов Рассмотрим следующий пример. /?-вектор, соответствующий дереву Т (рис. 2.35), есть (1, -4, 2, -2, 4, 3,21, -2, 5, 6, 8, 17, -3, 9, 11,20). Как нетрудно заметить, /?-вектор есть линейный код с ограничителями. Рис. 2.35. Дерево Т
Глава 2. Ориентированные деревья 87 Машинное представление деревьев с помощью адресной арифметики Данное представление есть практическая реализация принципа рассмотрения деревь- ев как графов данных. Формировать деревья с помощью адресной арифметики можно двумя способами. Идея первого способа применима при любом постоянном количе- стве дуг, выходящих из вершины, но мы изложим ее на примере двоичного дерева. Пусть имеется вектор памяти А. Тогда начинаем с кванта Л[1], делая его корнем де- рева, кванты А[2] и Л[3] — его непосредственными потомками. Вообще непосредст- венные потомки кванта А[к] — это кванты А [2 к] и А[2к+ 1]. По дереву, которое при этом получается, можно двигаться в обоих направлениях, т. к. из вершины А[к] мож- но перейти к ее потомкам, удвоив к или удвоив к и прибавив единицу, а можно в об- ратном направлении, к родителю вершины А[к], разделив к пополам и отбросив дробную часть. Можно было бы сделать корнем квант Л[0]; это оказывается удобнее для деревьев более общего вида. Другой способ, основанный на адресной арифметике, применим только для двоич- ных деревьев. Если для представления двоичного дерева используется вектор памяти от кванта / до кванта j включительно, то корнем делаем квант m = [(/ +J) / 2], т. е. се- редину вектора, в квантах от /-го до (т — 1)-го включительно размещаем левое отно- сительно корня поддерево, в квантах от (/и + 1 )-го до у-го включительно — правое относительно корня поддерево. 2.1.4. Перечисление и подсчет деревьев Помеченные деревья Теорема Кэли. Число tn помеченных деревьев с п вершинами равно t„ = л”-2- Теорема Скойнса. Число 2-раскрашенных деревьев с т вершинами одного цвета и п вершинами другого равно 8п — п т . Теорема Рида. Число помеченных гомеоморфно несводимых деревьев равно п /X h„ =(и-2)!У(-1)"-* ”1—---. lW-2)! Непомеченные деревья Пусть 7(х) = ^т;х" Л=1 производящая функция для корневых деревьев. Таким образом, Тп представляет со- бой число корневых деревьев с и вершинами.
88 Часть I. Обработка и визуализация графов Теорема Пойа. Перечисляющий ряд корневых деревьев удовлетворяет соотношению Т(х) — х exp{^V(x*)/к}. *=| Соотношение теоремы является функциональным уравнением, из которого выводит- ся следующая формула для Дх), принадлежащая Кэли: s7’(x) = xf[(l-x/’) V Р=1 Числа корневых деревьев с п вершинами для п < 26 найдены Риорданом, а для п < 39 — Швенком (табл. 2.1). Таблица 2.1. Число корневых деревьев N Т(п) п Т(л) п Т(п) 1 1 10 719 19 4688676 2 1 11 1842 20 12826228 3 2 12 4766 21 35221832 4 4 13 12486 22 97055181 5 9 14 32973 23 268282855 6 20 15 87811 24 743724984 7 48 16 235381 25 2067174645 8 115 17 634847 26 5759636510 9 286 1. 18 - 1721159 Здесь содержатся первые 26 значений функции Г(п). Следующая рекурсивная функция для вычисления Т(п) принадлежит Оттеру: пТ(п + 1) = Т(1) S(n, 1) + 27(2) S(n, 2) + ..+ пТ(п) S(n, m), где S(n,k) = X T(n + \-j + k). Пусть '(*) = £лх” производящая функция для деревьев, так что tn есть число деревьев с п вершинами.
Глава 2. Ориентированные деревья 89 Теорема Оттера. Ряд t(x), перечисляющий деревья, выражается через ряд Т(х) для корневых деревьев с помощью формулы /(х)=Т(х)- |(7’2(х)-7(х2)). Значения / для п < 26 вычислены Риорданом и приведены в табл. 2.2. Таблица 2.2. Значения t для п <26 п tn п tn п 1 1 10 106 19 317955 2 1 и 235 20 823065 3 1 12 551 21 2144505 4 2 13 1301 22 5623756 5 3 14 3159 23 14828074 6 6 15 7741 24 39299897 7 И 16 19320 25 104606890 8 23 17 48629 26 279793450 9 47 18 123867 Перечисление лесов Пусть перечисляющим многочленом для лесов с п вершинами будет функция и—1 <Z=0 где/,.</— число лесов с п вершинами и q ребрами. Тогда производящая функция для лесов имеет вид: /(х,у) = ^у"-/„(х). Л=1 Теорема Харари — Палмера. Перечисляющий многочлен для лесов с п вершинами имеет вид: = Х fl О) *=1 Гtk +Jk I Jk ) где сумма берется по всем разбиениям (J) числа п, at к — число деревьев с к вершинами. Для п = 6 многочлен f6(x) имеет вид Уё(х) = 1 + х + 2х2 + 4х3 + 6х4 + 6х5.
90 Часть I. Обработка и визуализация графов Число лесов выражается через число деревьев с помощью следующих формул, при- надлежащих Харари: 1 + /(х»3’) = ехР{^ £ (tk/n)(xk '/)"}, л=1 к=\ k=l Ориентированные деревья Пусть г(х) и 7?(х) — перечисляющие ряды для ориентированных и для корневых ори- ентированных деревьев соответственно. Теорема Харари — Принса. Перечисляющие ряды г(х) и R(x) для ориентированных и корневых ориентированных деревьев удовлетворяют соотношениям /?(х) = х(ехр{£ R(xk)lk})2 k=l И r(x) = R(x) - R2(x). Первые 21 коэффициент рядов г(х) и /?(х) найдены Риорданом. Значения коэффици- ентов т„ ряда г(х) и р„ ряда /?(х) приведены в табл. 2.3. Таблица 2.3. Значения коэффициентов тп ряда г(х) и рп ряда R(x) п Тп Рп п Тп Р" 1 1 1 7 350 2058 2 1 2 8 1376 9498 3 3 7 9 5743 44947 4 8 26 10 24635 216598 5 27 107 И 108968 1059952 6 91 458 12 492180 5251806 Гомеоморфно несводимые деревья Пусть Л(х), Я(х) и Н(х) обозначают перечисляющие ряды для следующих трех клас- сов гомеоморфно несводимых деревьев: "обычных", корневых и с висячими корнями. Теорема Харари— Прииса. Перечисляющие ряды Н(х), Н(х) и h(x) для гомео- морфно несводимых деревьев удовлетворяют соотношениям Н(х) = ехр{£ *=1 1 = х kxk !
Глава 2. Ориентированные деревья 91 1 I х I _________ Н(х) =----Н(х)-—(Н2(х')+Н(х2)), х 2х ,, , х -1 1 + х \ Л(х) - —— Н (х) + ——- Н (х). X X Для первых 12 членов ряд Д(х) имеет вид h(x) = х +х2 + х4 +х5 + 2хб + 2х7 + 4х8 + 5х9 + Юх10 +14хи + 26х12 + ... Плоские или упорядоченные деревья Если в плоском дереве (см. разд. 1.1.2) выделен корень, то практически имеем дело с упорядоченными деревьями. Для них имеет место Теорема Харари — Принса — Татта. Если Р(х), Р(х) и р(х) — перечисляющие ряды для соответствующих трех типов плоских деревьев: с висячими корнями, корневых и просто деревьев, то 1 [2/7 — 2 I п~1 л+1 P(x)=x£(Z(C„P(x)/x)), /7=0 р(х)=/’(х)-(Хх2)[Р2(х)-Р(х2)]- Несколько первых членов ряда р(х) имеют вид р(х) = х + х2 + х3 + 2х4 + Зх5 + 6хб + 14х7 + ... Ряд Р(х) является также перечисляющим рядом для таких плоских деревьев с вися- чими корнями, у которых каждая вершина имеет степень 1 или 3. Точнее, число пло- ских деревьев порядка п, имеющих висячие корни, совпадает с числом плоских де- ревьев с висячими корнями, обладающих и - 2 вершинами степени 3 ии-1 верши- нами степени 1. Двойственным к рассмотренному утверждению является следующее: ряд Р(х) перечисляет число способов триангулирования выпуклого /7-утольника, в котором одна из сторон выделена как корень и ориентирована; триангулирование при этом осуществляется путем проведения диагоналей, не имеющих точек пересечения, отличных от вершин /7-угольника. Коэффициенты ряда Р(х), называемые обычно числами Каталана, подсчитывают также число неассоциативных произведений с п сомножителями. Каркасы в неориентированном графе Число каркасов в неориентированном графе определяется с помощью следующей матричной теоремы о деревьях в графе. Пусть M(G) обозначает матрицу, получае- мую из матрицы A(G), где A(G) — матрица смежности графа G, с помощью подста- новки в ней на место Аго диагонального элемента числа deg vt.
92 Часть I. Обработка и визуализация графов Матричная теорема о деревьях для графов. Для всякого связного помеченного графа G все алгебраические дополнения матрицы M(G) равны друг другу и их общее значение представляет собой число каркасов графа G. Рассмотрим пример. Для графа G (рис. 2.36) с матрицей смежности 0 1 1 0 A(G)= 1 0 1 1 1 0 0 1 0 0 1 0 матрица M(G) имеет вид 2 -1 -1 0 -1 2 -1 0 M(G)= -1 -1 3 -1 0 0 -1 1 Алгебраическое дополнение, например, элемента йц равно 3. Соответствующие кар- касы графа G показаны на рис. 2.37 Рис. 2.36. Граф G Интересен также следующий результат. Пусть G— «-вершинный граф без петель и Во— его матрица инциденции с одной удаленной строкой (т. е. с п— 1 независимы- ми строками). Пусть В,— транспонированная матрица к Во. Тогда определитель |Во-Во| равен числу остовных деревьев графа G.
Гпава 2. Ориентированные деревья 93 Каркасы в ориентированных графах Число каркасов в ориентированном графе определяется с помощью аналогичной матричной теоремы о деревьях в орграфе. Пусть G — орграф с матрицей смежности A(G). Определим диагональную матрицу Moub У которой (/, /)-й элемент равен полу- степени исхода deg+ v, вершины v,. Затем положим Cout = M01lt — A(G). Аналогично определяется матрица Cin = M,n - A(G). Матричная теорема о деревьях для орграфов. Все алгебраические дополнения i-й строки матрицы СШ11 равны друг другу, и их общее значение есть число каркасов орграфа G, входящих в вершину v,. Двойственным образом общее значение алгебраи- ческих дополнений i-го столбца матрицы С,п равно числу каркасов, выходящих из вершины Vj. Рис. 2.38. Граф G Рассмотрим пример. Для графа G (рис. 2.38) матрицы Cout и С„ имеют вид: 2 -1 0 -1 0 2 -1 0 C0ut ~ 0 0 1 0 0 -1 -1 -1 -1 0 0 1 1 -1 0 -1 0 2 -1 0 С1П = 0 0 1 0 0 -1 0 -1 -1 0 0 2 Исходя из первой строки матрицы Сои, и из первого столбца матрицы С1П, убеждаемся что орграф G имеет в точности четыре каркаса, выходящих из вершины 1 (рис. 2.39), и два каркаса, входящих в эту вершину (рис. 2.40).
94 Часть I. Обработка и визуализация графов Рис. 2.39. Четыре каркаса, выходящих из вершины 1 орграфа G Рис. 2.40. Два каркаса, входящих в вершину 1 орграфа G 2.2. Обходы графов и деревьев в глубину и ширину Необходимость в алгоритмах обходов графов и деревьев в глубину и ширину возни- кает во многих приложениях. Например, они существенно используются при реше- нии задач искусственного интеллекта, являются базовыми в алгоритмах проверки
Гпава 2. Ориентированные деревья 95 связности, планарности и других свойств графов, а также в методах решения задач динамического распределения памяти. В данном разделе приводятся общие алгоритмы, осуществляющие разные обходы графов при различных реализациях их структур данных, алгоритмы обхода графа в глубину и ширину, ориентированные на разные представления графа, а также алго- ритмы основных способов обхода деревьев и лесов в глубину — в префиксном, ин- фиксном и постфиксном порядках. Все приведенные алгоритмы имеют линейную временную сложность. 2.2.1. Разметки, нумерации, обходы, укладки Пусть G = (X, U) — некоторый граф, состоящий из п вершин и m ребер (дуг), т. е. п- |Л] и m = |t/|. Разметкой вершин графа G называется функция из X в некоторое множество L, эле- менты которого называются пометками, а разметкой ребер (дуг) — функция из U в L. Граф G называется помеченным, если он снабжен хотя бы одной из таких разме- ток; и если пометки — числа, их часто называют весами, а помеченный граф — на- груженным. Отображение F множестваX на множество [1 : п] называется нумерацией графа G. Пусть F— некоторая нумерация. Через F[i: j] обозначается множество вершин а также подграф графа G, образованный этим множеством вершин. Дуга и = (р, q) ориентированного графа G с нумерацией F называется F-прямой дугой (F-дугой), если F(p) < F(q), и F-обратной дугой, если F(p) > F(q). Если некоторый Рис. 2.41. Лес обхода графа G
96 Часть I. Обработка и визуализация графов Рис. 2.42. Лес обхода ориентированного графа G путь по G отр до q не содержит F-обратных дуг, то он называется F-путем, а верши- на q является F-достижимой из вершины р. Укладкой Н длины к графа G называется любое отображение множества [1 : А], где к > п, на X. Укладка длины п называется обходом графа G Обычно укладка Н задает- ся в виде последовательности вершин (Я(1),..., Н(к)), где к — длина укладки. Подграф (X, Z) неориентированного (или ориентированного) графа G = (X, U) назы- вается лесом обхода Н графа G (обозначение Gh = (X Z)), если 7. содержит каждое такое ребро (соответственно каждую такую дугу) и е U, что среди вершин, располо- женных в Н между вершинами р = H(i) и q = H(j), где i < j и и = {p,q}, нет вершин, соединенных ребром (соответственно дугой) с вершиной H(j). На рис. 2.41, б изображен лес обхода Н = (2, 3, 1, 5, 6, 7, 4, 10, 9, 8, 12, 11, 13) гра- фа G, изображенного на рис. 2.41, а. Рис. 2.42, б содержит лес обхода Н = (2, 3, 8, 4, 7, 6, 1,5) ориентированного графа G с рис. 2.42, а. 2.2.2. Базисные нумерации Прямой нумерацией (или М-нумерациеи) ориентированного графа G - (X, U) называ- ется любая такая его нумерация F, что справедливы следующие два свойства: □ для любой вершины р либо в р заходит хотя бы одна F-прямая дуга, либо р не достижима из вершин, F-номера которых меньше F(p); □ если (р, q) — такая F-прямая дуга, что среди вершин с F-номерами из (F(p) F(q)) нет предшественников вершины р, то среди них нет и предшественников ни од- ной вершины, F-номер которой больше F(q). Нумерация F графа G называется его обратной нумерацией (или N-нумерацией), если существует такая прямая нумерация М графа G, что для любых вершин р и q нера- венство F(p) < F(q) выполняется тогда и только тогда, когда либо вершина q является Л/-ДОСТИЖИМОЙ из вершины р, либо M(q) < М(р) и вершина р не является М-дости- жимой из вершины q
Гпава 2. Ориентированные деревья 97 Прямая нумерация и связанная с ней обратная нумерация графа образуют пару его базисных нумераций. На рис. 2.43 для орграфа G (см. рис. 2.42, а) приведены рядом с вершинами (в скоб- ках) их номера в прямой и обратной нумерациях. Рис. 2.43. Прямая и обратная нумерации вершин орграфа G Рис. 2.44. Разные базисные нумерации одного и того же орграфа 4 Зак. 202
98 Часть I. Обработка и визуализация графов Справедливы следующие свойства. А. Для любой прямой нумерации Мграфа G и любого простого пути Р = (pt, ps) по G такого, что М(р() = min{A7(p,) .j е [1 : s]}, все вершины Р являются М-достижи- мыми в G из (р\). Б. Пусть М— некоторая прямая нумерация графа G и Р\ = (рь ..., р*) а = (^i,.... qs) — такие М-пути по G, что М{р\) < M(q() ЛУ(р*) < M(qs). Тогда сущест- вует М-путь по G от q\ до рь- В. Каждый ориентированный граф обладает по крайней мере одной парой связан- ных базисных нумераций, причем обратная нумерация графа может соответство- вать нескольким его прямым нумерациям (см. рис. 2.44). 2.2.3. Обходы в ширину и глубину Пусть Н— некоторый обход неориентированного (или ориентированного) графа G = = (X, U), п = | X | и пусть Н„ где i е [1 : п], обозначает min({<} и {/’: H(J) е А}), где А — множество всех вершин, расположенных в Н левее вершины Н(ф), и смежных, т. е. соединенных ребром (соответственно дугой), с вершиной Н(1). Н называется обходом (поиском) в ширину графа G, начиная с р, если р = //(1) и для любых i,j е [ I : п] из i < j следует, что Н, < Hj. Н = (7, 2, 1, 6, 3, 4, 5, 10, 9, 8, 11, 12, 13) является обходом в ширину графа (см. рис. 2.41, а),аН= (2, 7, 3, 8, 4, 6, 5, 1)—- обходом в ширину ориентированного графа (см. рис. 2.42, а). Рис. 2.45. Граф б'для графа G
Гпава 2. Ориентированные деревья 99 Обход Н ориентированного графа G называется обходом (поиском) в глубину G, на- чиная с р, если Я(1) = р и /Г1 — прямая нумерация графа G. Например, Н = (2, 3, 8,4, 7,6,1, 5) является обходом в глубину графа G (см. рис. 2.43), начиная с вершины 2. Пусть Н— некоторый обход неориентированного графа G — (X, U). По отношению к Н множество U разбивается на множество древесных ребер, принадлежащих лесу Gh, и множество обратных ребер, не принадлежащих лесу Gh- Пусть G' обозначает ори- ентированный граф (X, W) такой, что (р, q) е W тогда и только тогда, когда — древесное ребро и р расположено в Н левее q, либо (p,q) — обратное ребро и q расположено в Н левее р. Н называется обходом в глубину G, начиная с р, если р = Я(1) и Н— обход в глубину графа G'. Для графа G на рис. 2.41, а и его обхода в глубину Н = (2, 3, 1, 5, 6, 7, 4, 10, 9, 8, 12, 11, 13) множества древесных и обратных дуг изображены на рис. 2.41, б сплошными линиями — древесные дуги, а штриховыми — обратные. Для них граф G' имеет вид, изображенный на рис 2.45. 2.2.4. Остовный лес обхода в глубину и глубинное остовное дерево Пусть Я— некоторый обход в глубину графа G = (X, U). Тогда лес Gh = (X, Z) обхода Н называется остовным лесом для G, построенным обходом в глубину Н, или глу- бинным остовным лесом для G. Если этот лес состоит из единственного дерева, (X, Z) называется глубинным остовным деревом. Вершина, с которой начинается обход Н, считается корнем указанного дерева. Рис. 2.46. Древесные обратные, поперечные и прямые дуги для обхода Н графа G Множество дуг ориентированного графа G = (X, U) распадается относительно его обхода в глубину Н на четыре множества: древесные — дуги, принадлежащие лесу обхода Я; обратные — дуги, идущие от потомков леса обхода к предкам (возможно, из вершины в себя); прямые — дуги, идущие от предков к потомкам, но не являю-
100 Часть I. Обработка и визуализация графов щиеся древесными или обратными; поперечные — дуги, соединяющие вершины, ко- торые не являются ни предками, ни потомками одна другой. На рис. 2.46 для обхода Н = (2,3,8,4,7,6,1,5) графа G (см. рис. 2.42, а) древесные дуги нарисованы сплошными "жирными" линиями, обратные— волнистыми, попереч- ные— штриховыми, а прямые дуги — сплошными "тонкими" линиями. 2.2.5. Рекурсивный алгоритм обхода графа в глубину -----------------------------Задача---------- Объекты. Ориентированный граф G. Требуется. Осуществить обход в глубину графа G. -------- Решение--------- Метод. Используя рекурсивную процедуру, линейный по временной сложности алгоритм обхода графа G в глубину можно записать следующим образом: проц РЕКУРСИВНЫЙ-ОБХОД(р вершина) = 1. Посетить вершину р; 2. для всех q из множества вершин, смежных с р цикл 3. если q еще не посещалась то 4. РЕКУРСИВНЫЙ-ОБХОД(д) все все все; начало 1. для всех р из множества вершин G цикл 2. если р еще не посещалась то 3. РЕКУРСИВНЫЙ-ОБХОД(р) все все; конец 2.2.6. Общий алгоритм обхода графа с запоминанием дуг --------Задач а---------- Объекты Ориентированный граф G, каждая вершина которого может находиться в одном из двух состояний; "помечена", "непомечена". Операции. Для любой вершины р графа G операция ПОМЕТИТЬ(р) выполнима, если р находится в состоянии "непомечена", и при своем выполнении переводит р в состояние "помечена", а предикат НЕ1ЮМЕЧЕНА(р) ложен, если р находится в
Гпава 2. Ориентированные деревья 101 состоянии "помечена". Предполагается, что процедура ПОМЕТИТЬ^) при своем выполнении осуществляет определенные действия с информационным содержимым вершины р, для реализации которых и производится обход графа. Дано. Задана вершина ро такая, что каждая вершина графа G, достижимая из р0, на- ходится в состоянии "непомечена". Требуется. Перевести в состояние "помечена" все вершины графа G, достижимые из/?с. ------Решен и е----- Метод. проц ЛЕС(ро вершина) = 1 S . семейство дуг = 0; 2 . q вершина = р0; 3 L начало ПОМЕТИТЬ(р); 4 . S с= ИСХОД(ч); 5 . пока S * 0 цикл 6 q := КОНЕЦ( Э S); 7 если НЕПОМЕЧЕНА(р) то начать L все все конец все Рассмотрим граф, изображенный на рис. 2.47 При выполнении ЛЕС(р0) состояние S меняется следующим образом: 0, {щ, и2, щ}, {и2, щ}, {w2, г<л}, {«з, ы4},{н4}, {иь, и5, и4}, {и5, и4}, и4}, 0 а вершины графа посещаются в следующей последовательности: Ро,Рг,Р\ Рис. 2.47. Исходный орграф G А. Временная сложность алгоритма составляет О(к) времени, где к— число дуг графа G, достижимых из вершины pft.
102 Часть I. Обработка и визуализация графов Б. Алгоритм изменяет состояние непомеченной вершины q тогда и только тогда, когда q достижима из р. В. Если S является стеком, то процедура помечает вершины графа G, достижимые из ро, в порядке поиска в глубину, а если S— очередь, то вершины помечаются в по- рядке поиска в ширину. 2.2.7. Общий алгоритм обхода графа с запоминанием его вершин -------Задача-------- Та же, что у общего алгоритма обхода графа с запоминанием дуг (см. разд. 2.2.6). ------Решен и е----- Метод. проц ЛЕС1(р0 •’ вершина) = 1 S семейство вершин = 0; 2 . S <- Ро, ПОМЕТИТЬ(ро); 3 пока S * 0 цикл 4 . <?:= э S; 5 . для всех р из ПРЕЕМ(р) цикл 6 если НЕПОМЕЧЕНА(р) то 7 ПОМЕТИТЬ(р); S <- р все все все все Рассмотрим выполнение ЛЕС1(ро), где р— вершина графа (см. рис. 2.47). В нем 5 принимает следующую последовательность значений: 0, (ро), 0, (Р2, Pi), (pi), 0- Свойства. Для алгоритма обхода графа с запоминанием его вершин справедливы все свойства алгоритма рассмотренного в разд. 2.2.6 с тем отличием, что если S явля- ется стеком, то ЛЕС1 может помечать вершины графа G, достижимые из рй, в поряд- ке, отличном от их обхода при поиске в глубину. 2.2.8. Алгоритм обхода графа в ширину с использованием внешней очереди ------- Задача------- Объекты. Упорядоченный ориентированный граф G, каждая вершица которого может находиться в одном из трех состояний: "непомечена", "помечена и непройде-
Гпава 2. Ориентированные деревья 103 на", "пройдена”, а каждая дуга— в одном из двух состояний: "пройдена", "непрой- дена" Операции. Для любой вершины q графа G операция ДУГА(д) выдает имя первой дуги, исходящей из q, либо пустую ссылку (ничто), если q— лист (т. е. нет исходя- щих из q дуг), ПОМЕТИТЬ^) переводит вершину q из состояния "непомечена" в со- стояние "помечена и непройдена", ПРОЙТИ-ВЕРШИНУ(^) переводит вершину q из состояния "помечена и непройдена" в состояние "пройдена", а предикат НЕПОМЕЧЕНА(^) выдает значение истина, если q находится в состоянии "непоме- чена". Для любой дуги w графа G операция СЛЕД(и’) выдает имя следующей дуги, исходя- щей из той же вершины, что и w, либо ничто, если w— последняя исходящая дуга, а ПРОЙТИ-ДУГУ(тг) переводит дугу w из состояния "непройдена" в состояние "прой- дена". Дано. Каждая дуга графа G, достижимая из заданной вершины р0, находится в со- стоянии "непройдена", а каждая вершина, достижимая из р0, — в состоянии "непоме- чена". Требуется. Перевести в состояние "пройдена" все вершины и дуги графа G, дос- тижимые из р0, выполняя над ними каждую из операций ПОМЕТИТЬ, ПРОЙТИ- ВЕРШИНУ и ПРОЙТИ-ДУГУ в порядке первого попадания в них при обходе графа G в ширину, начиная с р0. Рассмотрим пример. Для графа G (рис. 2.48, а) и его вершины 1 в состояние "пройде- ны" должны перейти все те его вершины и дуги, которые образуют дерево, изобра- женное на рис. 2.48, б. Вершины проходятся (и помечаются) в порядке 1, 2, 5, 6, 3, 4, а(1,2), (1,5), (1,6), (2,3), (3,4) — порядок прохождения дуг. Рис. 2.48. Обход графа с использованием внешней очереди ------Решен и е----- Метод. проц ОБХОД-В-ШИРИНУ(₽о вершина) = 1. Q очередь вершин = 0, 2. От- р0, ПОМЕТИТЬ(ро);
104 Часть I. Обработка и визуализация графов 3 4. пока Q * 0 цикл q = э Q; w = ДУГА(р); 5. 6. 7 8 9 пока w* ничто цикл ПРОЙТИ-ДУГУ(1у); р - КОНЕЦ(и-); если НЕПОМЕЧЕНА(р)то ПОМЕТИТЬ(р); Q <- р все; 10. w = СЛЕД(м) все; 11. ПРОЙТИ-ВЕРШИНУ(р) все все Процедура ОБХОД-В-ШИРИНУ базируется на алгоритме, рассмотренном в разд. 2.2.7. В ней уточняются реализация семейства S, а также действия цикла 5—7 по последовательному выбору всех преемников вершины q. Кроме этого в процедуру ОБХОД-В-ШИРИНУ добавляются действия по прохождению дуг, а действия по про- хождению вершин разбиваются на две части — ПОМЕТИТЬ и ПРОЙТИ-ВЕРШИНУ. А. Временная сложность алгоритма составляет O(k+i) времени, где к и t — количе- ства дуг и вершин графа G, достижимых из ро. Б. При выполнении ОБХОД-В-ШИРИНУ(ро) операция ПОМЕТИТЬ применяется к любой вершине q, достижимой из ро, перед обработкой операцией ПРОЙТИ-ДУГУ всех дуг м, исходящих из q, а операция ПРОЙТИ-ВЕРШИНУ— после этой обра- ботки. В. В каждый момент выполнения ОБХОД-В-ШИРИНУ(ро) размер очереди Q не пре- вышает величины t — 1, где t — число вершин графа G, достижимых из ро- 2.2.9. Алгоритм обхода графа в ширину с использованием внутренней очереди ------- Задача------- Объекты Ориентированный граф G и некоторая вершина q, не принадлежащая графу G. Вершины графа могут находиться в одном из двух состояний: "непомече- на", "помечена". Вершине q и каждой вершине графа G приписан атрибут СЛЕД, значением которого может быть имя любой вершины графа. Операции. Для любой вершины р графа G логическая операция НЕПОМЕЧЕНА(р) выдает значение истина, если р в состоянии "непомечена", операция ПРОЙТИ- ВЕРШИНУ(р) переводит вершину из состояния "непомечена" в состояние "поме- чена" Дано. Каждая вершина графа G находится в состоянии "непомечена", а значением д.СЛЕД является имя некоторой вершины ро графа G.
Глава 2. Ориентированные деревья 105 Требуется. Перевести в состояние "помечена" все вершины графа G, достижимые из р0, выполняя над ними операцию ПРОЙТИ-ВЕРШИНУ в порядке первого попада- ния в них при обходе графа G в ширину, начиная с р0. ---------------------------Решение----------- Метод. проц ОБХОД-В-ШИРИНУ-1 = 1. р := р.СЛЕД; ПРОЙТИ-ВЕРШИНУ(р); 2. пока p*q цикл 3. q = q. СЛЕД, 4. для всех г из ПРЕЕМ(р) цикл 5. если НЕПОМЕЧЕНА(г)то 6. ПРОЙТИ-ВЕРШИНУ(г); 7 р СЛЕД = г. р := г все все все р.СЛЕД := ничто все Процедура ОБХОД-В-ВЕРШИНУ-1 является уточнением алгоритма, рассмотренного в разд. 2.2.7 В ней с помощью вершины q и атрибута СЛЕД реализуется S в режиме очереди: если р = q, то очередь .S' пуста; при p^q очередь состоит из элементов р.СЛЕД, (р.СЛЕД). СЛЕД, ..., р0. Оператор 3 исключает элемент из очереди, а опера- тор 7 добавляет новый элемент в очередь. Свойства. 1. Время выполнения ОБХОД-В-ШИРИНУ-1 составляет O(k+t) времени, если к и t — количество дуг и вершин графа G, достижимых из р0 соответственно. 2. После завершения выполнения процедуры ОБХОД-В-ШИРИНУ-1 последователь- ность ро, р0.СЛЕД, ро.СЛЕД.СЛЕД,..., р, где р.СЛЕД - ничто, содержит все вершины графа G, достижимые из р0, причем в порядке применения к ним операции ПОСЕТИТЬ-ВЕРШИНУ. 2.2.10. Алгоритм обхода графа в ширину без использования дополнительной памяти -------- Задача------- Объекты. Упорядоченный ориентированный граф G, каждая вершина которого мо- жет находиться в одном из трех состояний: "непомечена", "помечена и непройдена" и "пройдена", а каждая дуга — в одном из двух состояний: "пройдена" и "непройдена". Каждой вершине и дуге графа G приписан атрибут СВЯЗЬ, значением которого мо- жет быть имя любой вершины или любой дуги графа.
106 Часть I. Обработка и визуализация графов Операции. Помимо операций ПОМЕТИТЬ, ПРОЙТИ-ВЕРШИНУ, НЕПОМЕЧЕНА и ПРОЙТИ-ДУГУ, описанных в алгоритме (см. разд. 2.2.8), имеется логическая опе- рация СВЯЗЬ-ДУГА(£), значением которой является истина, если Е.СВЯЗЬ— это имя дуги. Дано. Каждая дуга w графа G, достижимая из заданной вершины р0, находится в состоянии "непройдена", причем значением атрибута м>.СВЯЗЬ является либо имя следующей дуги, исходящей из той же вершины, что и w, либо ничто, если w — по- следняя исходящая дуга. Каждая вершина р графа G, достижимая из р0, находится в состоянии "непомечена", причем значением атрибута р.СВЯЗЬ является либо имя первой дуги, исходящей из р, либо ничто, если р — лист. Требуется. См. алгоритм, рассмотренный в разд. 2.2.8. -------Решен ие----- Метод. проц ОБХОД-В-ШИРИНУ-2(ро. вершина)= 1. F =ро, V:=po ПОМЕТИТЬ(ро); 2. пока Е.СВЯЗЬ * ничто цикл F := Е.СВЯЗЬ все; 3. пока V* ничто цикл 4. Е - V; 5 пока(Е.СВЯЗЬ * ничто) СВЯЗЬ-ДУГА(Е) цикл 6. Е = Е СВЯЗЬ ПРОЙТИ-ДУГУ(Е); 7 q = КОНЕЦ(Е); 8. если НЕПОМЕЧЕНА(д) то 9. Е.СВЯЗЬ = q;F:=q, 10. ПОМЕТИТЬ(Е); 11 пока F СВЯЗЬ + ничто цикл 12. F.=F СВЯЗЬ все все все; 13 ПРОЙТИ-ВЕРШИНУ(У); 1/ = Е.СВЯЗЬ; 14. Е.СВЯЗЬ = ничто все все Процедура ОБХОД-В-ШИРИНУ-2 базируется на алгоритме, рассмотренном в разд 2.2.8, но использует для реализации очереди вместо внешней памяти места рас- положения пустых ссылок, с необходимостью возникающие при стандартном пред- ставлении графа списками исходящих дуг. Она поддерживает очередь в виде множе- ства вершин и дуг, связанных в односторонний список значениями атрибута СВЯЗЬ, который содержит вместе с каждой помеченной вершиной все исходящие из нее дуги (см. рис. 2.49, на котором схематично изображено представление графа с рис. 2.48, а в тот момент, когда вершины 1, 2 и 5 перешли в состояние "помеченных"). Когда вершина q помечается (см. строку 10 процедуры), включаются в очередь она сама
Гпава 2. Ориентированные деревья 107 (строка 9) и все исходящие из нее дуги (строки 11, 12). После прохождения вершины (строка 13), ничто опять становится значением атрибута СВЯЗЬ последней дуги, ис- ходящей из этой вершины (строки 13, 14). В процедуре ОБХОД-В-ШИРИНУ-2 ис- пользуются три локальные переменные: V— вершина, которая проходится; Е— об- работанный элемент списка, реализующего очередь; F— последний элемент этого списка. А. Алгоритм требует на выполнение О(к + /) времени, где к и t — количество дуг и вершин графов, достижимых из р0. Б. В процессе выполнения процедуры ОБХОД-В-ШИРИНУ-2(рй) каждый элемент списка дуг, достижимых из р0, обрабатывается дважды: первый раз только для установки F (строки 2 и 11, 12), а второй — при выполнении ПРОЙТИ-ДУГУ (стро- ка 6). Рис. 2.49. Граф, содержащий очередь Начало очереди 2.2.11. Алгоритм обхода в ширину графа с циклическими списками дуг -------- Задача------- Объекты и операции. Те же, что и в алгоритме обхода графа в ширину без использования дополнительной памяти разд. 2.2.10. Дано. Каждая дуга графа G, достижимая из заданной вершины р0, находится в со- стоянии "непройдена", причем каждое множество дуг, исходящих из одной и той же вершины, через атрибут СВЯЗЬ связано в циклический список. Каждая вершина q
108 Часть I. Обработка и визуализация графов графа G, достижимая из р0, находится в состоянии "непомечена", причем значением атрибута «/.СВЯЗЬ является либо имя одной из дуг, исходящих из q, либо ничто, если q— лист. Требуется. См. алгоритм, представленный в разд. 2.2.8. --------Решен и е----------- Метод. проц ОБХОД-В-ШИРИНУ-3 (р0 . вершина) = 1. V =po; ПОМЕТИТЬ(ро); 2. если ро СВЯЗЬ = ничто то 3. F := ро 4. иначе F = р0.СВЯЗЬ, ро СВЯЗЬ = Е.СВЯЗЬ; 5. Е.СВЯЗЬ := ничто все; 6. пока V* ничто цикл 7 E = V; 8. пока СВЯЗЬ-ДУГА(Е) цикл 9. Е - Е.СВЯЗЬ; ПРОЙТИ-ДУГУ(Е); р - КОНЕЦ(Е); 10. если НЕПОМЕЧЕНА(р) то 11. ПОМЕТИТЬ(р);Е.СВЯЗЬ := р; 12. если р СВЯЗЬ = ничто то 13. F=p 14 иначе F '= р.СВЯЗЬ; р.СВЯЗЬ := Е.СВЯЗЬ; 15. Е.СВЯЗЬ := ничто все все все; 16. ПРОЙТИ-ВЕРШИНУ(У); 17 если У= Его 18 V := Е.СВЯЗЬ; Е.СВЯЗЬ := ничто 19. иначе (V, У.СВЯЗЬ, Е.СВЯЗЬ) := (Е.СВЯЗЬ, Е.У.СВЯЗЬ) все все все В отличие от алгоритма, рассмотренного в разд. 2.2.!0, процедура ОБХОД-В- ШИРИНУ-3 не обрабатывает списки исходящих дуг дважды (ликвидируется первая обработка, целью которой является перевычисление F). Это достигается за счет не- традиционного представления графа G: множества исходящих дуг образуют по атри- буту СВЯЗЬ не односторонние списки, а односторонние циклы (см. рис. 2.49 и 2.50, а). После того как метится некоторая вершина w (операторы 1 и 11), разрывает- ся односторонний цикл исходящих дуг между его первой и последней дугами, добав- ляются w и ее исходящие дуги к концу очереди, перевычисляется F (см. рис. 2.50. б). После выполнения операции ПРОЙТИ-ДУГУ(Е) восстанавливается односторонний
Гпава 2. Ориентированные деревья 109 цикл дуг, исходящих из w (операторы 17—19). Некоторое увеличение размера про- цедуры ОБХОД-В-ШИРИНУ-3 по отношению к ОБХОД-В-ШИРИНУ-2 объясняется тем фактом, что пустые циклы дуг требуют специальной обработки. 2.2.12. Способы прохождения бинарных деревьев Для прохождения бинарного дерева в глубину можно воспользоваться тремя спосо- бами. проходить вершины в префиксном (или прямом) порядке, в инфиксном (или обратном) порядке и, наконец, в постфиксном (или концевом) порядке. Эти три спо- соба определяются рекурсивно следующим образом. В случае, когда бинарное дерево пусто, оно проходится без выполнения каких-либо действий; в противном же случае прохождение состоит из трех действий, одних и тех же для разных способов, но вы- полняемых в разных последовательностях: префиксный порядок— посетить корень, пройти левое поддерево, пройти правое поддерево; инфиксный порядок— пройти левое поддерево, посетить корень, пройти правое поддерево; постфиксный поря- док— пройти левое поддерево, пройти правое поддерево, посетить корень. Применяя это определение к бинарному дереву с рис. 2.51, получаем, что при префиксном по- рядке прохождения вершины посещаются в последовательности 1, 2, 3, 4, 5, 6, 7, 8, 9, при инфиксном — 3, 2, 1,5, 6, 4, 8, 7, 9, а при постфиксном порядке — 3, 2, 6, 5, 8, 9, 7,4,1
110 Часть I. Обработка и визуализация графов Рис. 2.51. Бинарное дерево 2.2.13. Алгоритм обхода бинарного дерева в глубину с внешним стеком ------- Задача--------- Объекты. Бинарные деревья, каждая вершина которых может находиться в одном из двух состояний: "непройдена", "пройдена" Операции. Для любого имени дерева Топерация КОРЕНЬ(Т) выдает корень дере- ва с именем Т, а операции ЛДЕРЕВО(Т) и ПДЕРЕВО(Т)— имена деревьев, являю- щихся соответственно левым и правым поддеревьями дерева с именем Т. Операция ПРОЙТИ-ВЕРШИНУ(р) переводит любую заданную вершину р из состояния "не- пройдена" в состояние "пройдена". Дано. Каждая вершина заданного бинарного дерева Т находится в состоянии "не- пройдена". Требуется. Перевести все вершины дерева Т в состояние "пройдена", выполняя над ними операцию ПРОЙТИ-ВЕРШИНУ в инфиксном порядке обхода дерева. --------Решение----------- Метод. проц ОБХОД-ДЕРЕВА(Т дерево) = 1. S: стек деревьев * 0; 2. D дерево = 7; 3. L: цикл 4. если D = ничто то 5. если S = 0 то 6 закончить L 7. иначе D := э S все; 8. ПРОЙТИ-ВЕРШИНУ(КОРЕНЬ(О)) 9. D - ПДЕРЕВО(О)
Гпава 2. Ориентированные деревья 111 10. иначе S <- D, D := ЛДЕРЕВО(О) все все все Алгоритм осуществляет инфиксный порядок прохождения вершин дерева. Когда вы- полнение достигает оператора 10, правила обхода требуют обработки того дерева R, имя которого хранится в переменной D. Поэтому имя дерева R сохраняется в стеке £, а затем проходится левое поддерево дерева R. Когда прохождение левого поддерева завершается, выполняется оператор 7 для извлечения запомненного имени R из стека. После прохождения корня дерева R (оператор 8) обработка дерева заканчивается прохождением правого поддерева (оператор 9). А. Начиная с любого выполнения оператора 4, при котором D ничто, алгоритм осуществляет прохождение в инфиксном порядке дерева D, а затем возвращается к выполнению оператора 4 с тем же состоянием стека S,ho с D = ничто. Б. Глубина стека S не превышает глубины дерева Т В. Если в процедуре ОБХОД-ДЕР ЕВА оператор 8 перенести в начало оператора 10, разместив его перед "S <— D", будет получена процедура, реализующая префиксный обход дерева. 2.2.14. Алгоритм обхода в глубину прошитого бинарного дерева Объекты. Бинарные деревья, каждая вершина которых может находиться в одном из двух состояний: "непройдена", "пройдена" Вершинам дерева приписаны атрибуты ЛСВЯЗЬ и ПСВЯЗЬ, значениями которых являются имена его вершин. Операции. Для любой вершины р, дерева Т логические операции ПВНИЗ(р) и ЛВНИЗ(р) выдают истинные значения, если текущие значения атрибутов р.ПСВЯЗЬ ир.ЛСВЯЗЬ— это имена вершин, являющихся потомками вершины р. Смысл опера- ций КОРЕНЬ и ПРОЙТИ-ВЕРШИНУ см. в разд. 2.2.13. Дано. Каждая вершинар дерева Тнаходится в состоянии "непройдена" и имеет сле- дующие значения атрибутов: р.ЛСВЯЗЬ = <у, если q— корень левого поддерева вер- шины р либо пусто правое поддерево у р и q— предшественник р при инфиксном порядке прохождения Т, и ЛСВЯЗЬ = ничто в противном случае; р.ПСВЯЗЬ = q, если q— корень правого поддерева вершины р либо пусто правое поддерево у р и q — преемник р при инфиксном порядке прохождения Т, и р.ПСВЯЗЬ = ничто в против- ном случае (на рис. 2.52 приведены значения атрибутов ЛСВЯЗЬ и ПСВЯЗЬ для вершин дерева Т из рис. 2.51). Требуется. См. алгоритм, рассмотренный в разд. 2.2.13. Метод. функ СЛЕД(р вершина) = 1. q = р.ПСВЯЗЬ,
112 Часть I. Обработка и визуализация графов 2. если ПВНИЗ(р) то 3. пока ЛВНИЗ(д) цикл 4. q := q. ЛСВЯЗЬ все все 5. возврат q все; проц ОБХОД-ПРОШИТОГО-ДЕРЕВА(Т дерево) = 1. р = КОРЕНЬ(Т); 2. пока ЛВНИЗ(р) цикл р = р.ЛСВЯЗЬ все; 3. пока р * ничто цикл 4. ПРОЙТИ-ВЕРШИНУ(р); р - СЛЕД(р) все все Рис. 2.52. Бинарное прошитое дерево Для любой вершины р функция СЛЕД вычисляет имя вершины, следующей за р в инфиксном порядке обхода дерева, либо выдает ничто, если р — последняя верши- на. Оператор цикла 2 присваивает переменной р имя вершины, с которой начинается инфиксный обход дерева. А. Атрибуты ЛСВЯЗЬ и ПСВЯЗЬ каждой вершины дерева проверяются ровно один раз. Б. Число выполнений операции ПРОИТИ-ВЕРШИНУ равно числу вершин в дереве. 2.2.15. Замечания Д. Кнут в своих книгах описал реализации алгоритмов, описанных в разд. 2.2.13 и 2.2 14, в виде MIX-программ, для выполнения первой из которых требуется 15и + г+3 единиц времени, а второй— 1 In-г + 8, где п— число вершин дерева, г — число вершин, не имеющих правых поддеревьев. Прохождение прошитых деревьев не только требует меньше памяти (в процедуре ОБХОД-ПРОШИТОГО-ДЕРЕВА нет стека, который есть в процедуре ОБХОД-
Гпава 2. Ориентированные деревья 113 ДЕРЕВА), но и осуществляется несколько быстрее; в случае гипотетической вычис- лительной машины MIX отношение затрачиваемых времен равно примерно 3:2. Прошитые деревья растут почти так же просто, как и обычные, причем связи-нити (т. е. ссылки вверх по дереву) можно использовать для вычисления по имени любой вершины р, следующей за ней вершины в префиксном порядке и предыдущей к ней вершины в инфиксном или постфиксном порядке. Эффективность при этом будет такой же, как и при работе алгоритма, рассмотренного в разд. 2.2.14 [10]. Алгоритм, рассмотренный в разд. 2 2.14 по существу не пользуется связями-нитями ЛСВЯЗЬ; поэтому в функции СЛЕД строку 2 можно заменить на "если ЛВНИЗ(р) ничто то" и тем самым получить вариант алгоритма, представленного в разд. 2.2.14 для прохождения в инфиксном порядке так называемых правопрошитых деревьев (т. е. в которых проводятся только связи-нити ПСВЯЗЬ). 2.2.16. Алгоритм обхода бинарного дерева в глубину без использования дополнительной памяти --------Задача------------ Объекты. Бинарные деревья и некоторая вершина q0, не принадлежащая деревьям. Вершины деревьев и q0 имеют по три атрибута: НОМЕР, ЛСВЯЗЬ и ПСВЯЗЬ. Значе- ниями атрибута НОМЕР являются целые числа из отрезка [0,3], а атрибутов ПСВЯЗЬ и ЛСВЯЗЬ — имена вершин. Дано. Имя корня дерева Т является значением атрибута до.ПСВЯЗЬ, а % HOMEP = 2. Значения атрибутов любой вершины q дерева Т удовлетворяют следующим свойствам: <7.НОМЕР = 0; (/.ЛСВЯЗЬ = р, если р— левый сын q\ <?.ПСВЯЗЬ =р, если р— правый сын q; q. Л С ВЯЗЬ = ничто, если пусто левое подде- рево дерева с корнем q; <7.ПСВЯЗЬ = ничто, если пусто правое поддерево дерева с корнем q. Требуется. Обойти в глубину дерево Т, заходя в каждую вершину р ровно три раза и увеличивая значение атрибута р.НОМЕР на единицу при каждом заходе в вершину р. --------Решен и е--------- Метод. проц ОБХОД-ДЕРЕВА-1 = 1. р = qo ПСВЯЗЬ; q = q0 2. пока p*qo цикл 3. р.НОМЕР := р.НОМЕР + 1; 4. L ' если р.НОМЕР = 3 то (р, р. ЛСВЯЗЬ, р. ПСВЯЗЬ, q) = (р.ЛСВЯЗЬ, р ПСВЯЗЬ, q, р) 5 иначе если р.ЛСВЯЗЬ * ничто то 6. если р.ЛСВЯЗЬ.НОМЕР = 0 то
114 Часть I. Обработка и визуализация графов 7. (р, р.ЛСВЯЗЬ, р.ПСВЯЗЬ, д) := (р.ЛСВЯЗЬ, р.ПСВЯЗЬ, q, р). 8. завершить L все; 9 (р.ЛСВЯЗЬ, р.ПСВЯЗЬ, д) := (р.ПСВЯЗЬ, q, р.ЛСВЯЗЬ) все все все все В отличие от алгоритма, рассмотренного в разд. 2.2.13, хранение пути от корня к об- рабатываемой вершине р осуществляется не с использованием дополнительной па- мяти (в процедуре ОБХОД-ДЕРЕВА для этого используется стек S), а внутри дерева путем моделирования стека через значения атрибутов НОМЕР, ЛСВЯЗЬ, ПСВЯЗЬ вершин дерева. При этом q— это верх стека S, а для любой вершины w имеем: и. НОМЕР = 0, если w еще не включалась в S; и.НОМЕР = 1, если w находится в5и обрабатывается левое поддерево вершины w; и.НОМЕР = 2, если и’ находится в S и обрабатывается правое поддерево w; и .НОМЕР = 3, если w уже удалена из S. Эта до- полнительная информация о вершинах позволяет моделировать S=(pt = q, ps-\, ..., р0), запоминая имя любой вершины рм как значение атрибута вершины рм; либо атрибута р,. ЛСВЯЗЬ, если р,.НОМЕР=1, либо атрибута р,. ПСВЯЗЬ, если р,.НОМЕР = 2 (рис. 2.53; значения атрибута НОМЕР указаны рядом с соответствую- щими вершинами дерева). Использования виртуального корня q0 можно избежать, заменив оператор 1 в про- цедуре ОБХОД-ДЕРЕВА-1 на оператор (р, q)(КОРЕНЬ(Т), КОРЕНЬ(Т)) и условие в операторе 2 на выражение р.НОМЕР 3. Рис. 2.53. Обход бинарного дерева в глубину без использования дополнительной памяти
Гпава 2. Ориентированные деревья 115 2.2.17. Обход в глубину произвольных деревьев и лесов От бинарных деревьев можно перейти к обычным, используя естественное соответ- ствие между упорядоченными лесами и бинарными деревьями. Указанное соответствие определяется таким образом, что для упорядоченного леса L и соответствующего ему бинарного дерева Т справедливы следующие свойства: □ L и Т имеют одно и то же множество вершин; П вершина р является левым сыном вершины q в Т тогда и только тогда, когда р — левый сын у q в L; П вершина р является правым сыном вершины qnT тогда и только тогда, когда р — брат вершины q в L либо р — корень такого дерева, которое непосредственно сле- дует в £ за деревом с корнем q. В рамках этого соответствия способы прохождения бинарного дерева (см. разд. 2.2.12), использованные к упорядоченным лесам, принимают следующий вид: префиксный порядок-— посетить корень первого дерева, пройти поддеревья первого дерева (в префиксном порядке), пройти оставшиеся деревья (в префиксном порядке); инфиксный порядок— пройти поддеревья первого дерева (в инфиксном порядке), посетить корень первого дерева, пройти оставшиеся деревья (в инфиксном порядке); постфиксный порядок— пройти поддеревья первого дерева (в постфиксном поряд- ке), пройти оставшиеся деревья (в постфиксном порядке), посетить корень первого дерева. Например, для леса, записанного с помощью вложенных скобок (А(В,С(К)), D(E(H),F(J),G)) префиксный порядок определяет последовательность А, В, С, К, D, Е, Н, F, J, G, инфиксный порядок — В, К, С, А, Н, Е, J, F, G, D, а постфиксный поря- док — К, С, В, Н, J, G, F, E,D,A. В прошитом бинарном дереве, соответствующем заданному лесу, правые связи-нити идут от самого правого сына к отцу семьи. 2.2.18. Алгоритм обхода графа в глубину без использования дополнительной памяти --------Задача----------- Объекты. Упорядоченный ориентированный граф G с одной выделенной верши- ной q0, называемой фиктивной. Вершина </0 имеет единственного преемника, который обозначается через р0. Каждой вершине р графа G сопоставлено три атрибута: КД — число дуг, исходящих из р, МД — массив из р.КД имен вершин, а также НД — некоторое неотрицательное число, не превышающее р.КД. Дано. Значения атрибутов любой вершиныр удовлетворяют следующим свойствам: р.НД = 0 и для любого i е [1, р.КД] значением /?.МД[«] является имя /-го преемника вершины р.
116 Часть I. Обработка и визуализация графов Требуется. Для всех вершин р графа G, достижимых из р0, установить значения р.НД * 0, присваивая им ненулевые значения в порядке обхода графа в глубину, на- чиная с р0. --------Решение-------------- М етод. проц ОБХОД-В-ГЛУБИНУ (р0 : вершина) = 1. t вершина = ничто; 2 q : вершина = qD; 3. q0-НД - 1; р - р0.МД[1]; 4. L . начало д.МД[р.НД] = t; t =q, q •= р; 5. t1 начало 6. пока р.НД < q. КД цикл 7 р.НД=д.НД+1; 8. р=д.МД[д.НД]; 9. если р * ничто то 10. если р.НД = 0 то начать L все все все; 11. если р * ничто то 12. р = q; Q = t; 13. t=q.MD[q.HD]; 14. q.MD[q.HD] = p; 15. начать t1 все конец конец все Процедура уточняет алгоритм, рассмотренный в разд. 2.2.6, на основе идеи переклю- чения дуг в графе, позволяющей моделировать стек S без использования дополни- тельной памяти (см. разд. 2.2.12). Пусть /)=/,/2, • t„,— максимальная последова- тельность имен вершин графа, в которой /,+) = t, .МД[/,.НД] и /,+1 У ничто для всех i Тогда при выполнении процедуры ОБХОД-В-ГЛУБИНУ текущим состоянием стека 5 является последовательность «уМД^.НД + 1], <?.МД[<7.НД + 2],..., ^.МД^.КД], /,.МД[/,.НД + 1], /,.МД[г,.НД + 2], ..., А.МД[г,.КД],..., /„,.МД [/„.НД + 1], /,„.МД[/„,.НД + + 2],..., /,„. МД[/„,.КД]; причем операторы 1—3 устанавливают стек пустым и р рав- ным р0, оператор 4 добавляет в стек преемников вершины р, оператор 7 помечает вершину как пройденную, а операторы 5—15 — это реализация цикла 5—7 процеду- ры ЛЕС (см. разд. 2.2.6). Свойства. После завершения выполнения алгоритма атрибуты любой вершины р удовлетворяют следующим свойствам. д.НД > 0, если р достижима из /)0; р.КД равно числу дуг, исходящих из д; для всех I значением р.МД[/] является имя /-го преемника вершины р.
Гпава 2. Ориентированные деревья 117 2.2.19. Алгоритм прямой нумерации вершин графа --------Задача---------- Объекты. Упорядоченный ориентированный граф G, каждой вершине которого сопоставлен атрибут М— некоторое целое из отрезка [0, и], где п-— число вершин из G. Операции. Для любых вершины р и дуги w операция ПДУГА(р) выдает имя пер- вой дуги, исходящей из ру либо ничто, если р— лист, а СДУГА(м)— имя следую- щей дуги, исходящей из той же вершины, что и w, либо ничто, если дуга w послед- няя. Операция ПОСЕТИТЬ — произвольная, не изменяющая G. Да н о. М = 0 для любой вершиныр графа G. Требуется. В качестве значений атрибута Мсопоставить всем вершинам графа G их номера в прямой нумерации. ----------------------------- Решение----------- Метод. проц НОМЕР (р вершина; NM целое) = 1 S стек дуг =0; 2 р.М - NM, NM -NM+V, 3. iv = ПДУГА(р); ПОСЕТИТЬ(р); 4. L цикл 5 если iv * ничто то 6. р - КОНЕЦ(м); 7 7 если р.М - 0 то 8 S <- w; w •= ПДУГА(р); ПОСЕТИТЬ(р), 9. р.М = NM; NM - NM + 1 10. иначе w := СДУГА(гу) все 11. иначе если S = 0 то завершить L 12. иначе w = СДУГА( э S) все все все все; проц ПРЯМАЯ-НУМЕРАЦИЯ = 1. MW-1: 2. для всех р из множества вершин графа G цикл 3. если р.М = 0 то НОМЕР(р, NM) все все все Действие процедуры ПРЯМАЯ-НУМЕРАЦИЯ на граф G то же, что и при обращении НОМЕРА, 0), где q0— фиктивная вершина, соединенная дугой с каждой вершиной графа G, а ИОМЕР(г/0, 0) осуществляет обход в глубину расширенного графа (т е
118 Часть I. Обработка и визуализация графов графа G с фиктивной вершиной q0), начиная с вершины q0 и приписывая вершинам расширенного графа в качестве их атрибутов М элементы последовательности чисел О, 1,2,..., п, в порядке первого попадания в вершины. А. Каждый оператор процедур ПРЯМАЯ-НУМЕРАЦИЯ и НОМЕР выполняется не более тах(«, т) раз, где т — число дуг графа G, а операция ПОСЕТИТЬ применяется к каждой вершине графа G ровно один раз, причем ее применение к вершинам графа осуществляется в порядке возрастания их М-номеров. 2.2.20. Алгоритм базисных нумераций графа -------- Задача--------- Объекты. Упорядоченный ориентированный граф G, каждой вершине которого сопоставлены два атрибута: М и N— числа из отрезка [0, п], где п— число вершин графа G. Операции. Помимо операций ПДУГА, СДУГА и ПОСЕТИТЬ, описанных в разд. 2.2.19, имеются четыре операции: ПРОЙТИ-ДУГУ-ДЕРЕВА, ПРОЙТИ- ПРЯМУЮ-ДУГУ, ПРОЙТИ-ПОПЕРЕЧНУЮ-ДУГУ и ПРОЙТИ-ОБРАТНУЮ- ДУГУ, каждая из которых относит к соответствующему классу ту дугу графа, кото- рая указана в качестве ее параметра. Дано. p.M=Q np.N=0 для любой вершины/? графа G. Требуется. Сопоставить в качестве значений атрибутов М и N базисные нумера- ции графа (см. разд. 2.2.2) и отнести каждую дугу графа к подходящему классу относительно дерева поиска в глубину (см. разд. 2.2.4). ---------Решен и е--------- Метод. проц БАНУМ (р : вершина; NM, NN целое) = 1. S' стек дуг = 0; 2. p.M -NM,NM:=NM+V,r\=p\ 3. w := ПДУГА(р); ПОСЕТИТЬ(р); 4. г = р\ 5. L. цикл 6. если w ф ничто то 7 р = KOHEU(iv); 8. если р./И=0то 9. ПРОЙТИ-ДУГУ-ДЕРЕВА(ку); 10. S <- w, w := ПДУГА(р); ПОСЕТИТЬ(р); 11. р.М := NM; NM := NM +1; 12. г=р 13. иначе если p.N ф 0 то 14. если г.М < р.М то 15. ПРОЙТИ-ПРЯМУЮ-ДУГУМ
Гпава 2 Ориентированные деревья 119 16 иначе ПРОЙТИ-ПОПЕРЕЧНУЮ-ДУГУ(1л/) все 17 иначе ПРОЙТИ-ОБРАТНУЮ-ДУГУ(и/) все; 18 и/:=СДУГА(и/) все 19 иначе r.N := Л/Л/; NN = NN - 1; 20 если S = 0 то завершить L 21. иначе w ;= э S; г := HA4AJlO(iv); w := СДУГА(м) все все все все; проц БАЗИСНЫЕ-НУМЕРАЦИИ = 1. NM - 1; NN := п; 2. для всех р из множества вершин графа G цикл 3. если р.М = 0 то БАНУМ(р, NM, NN) все все все Приведенная программа написана на основе алгоритма, рассмотренного в разд. 2.2.19 и свойствах М и N нумераций (см. разд. 2.2.2). Переменная г хранит имя вершины, являющейся верхом стека вершин. А. При выполнении алгоритма каждый оператор процедур БАЗИСНЫЕ- НУМЕРАЦИИ и БАНУМ выполняется не более тах(п, т) раз, где т — число дуг гра- фа G, а операция ПОСЕТИТЬ применяется к каждой вершине графа ровно один раз, причем вершины графа обрабатываются этой операцией в порядке возрастания их М-номеров. Б. Заменив в строке 1 процедуры БАЗИСНЫЕ-НУМЕРАЦИИ оператор NN := п на оператор NN := 1, а в строке 19 процедуры БАНУМ оператор NN := NN — 1 на опе- ратор NN ’= NN, получаем процедуру, вычисляющую дополнительную нумерацию в атрибутах N вершины графа. 2.2.21. Алгоритм обхода графа в глубину с двусторонним прохождением дуг графа --------Задача------------ Объекты. Упорядоченный ориентированный граф G, каждая вершина которого может находиться в одном из двух состояний: "помечена", "непомечена". Операции. Помимо операций ПДУГА, СДУГА и ПОСЕТИТЬ, описанных в разд. 2 2.19, имеются операции В ПЕРЕД-ПО-ДЕРЕВУ, Н АЗ АД-ПО-ДЕРЕВУ, ВПЕРЕД-ВНЕ-ДЕРЕВА и НАЗАД-ВНЕ-ДЕРЕВА, не изменяющие граф G, а также ПОМЕТИТЬ и НЕПОМЕЧЕНА, первая из которых, будучи примененной к некоторой
120 Часть I. Обработка и визуализация графов вершине, переводит ее в состояние "помечена", а вторая выдает истину, если указан- ная вершина находится в состоянии "непомечена" Дано. Каждая вершина графа G, достижимая из заданной вершины р0, находится в состоянии "непомечена". Требуется. В порядке обхода графа G в глубину, начиная ср0, перевести все вер- шины, достижимые из р0, в состояние "помечена" и выполнить над ними операцию ПОСЕТИТЬ, а также применить к каждой дуге w графа G, достижимой из р0, опера- ции ВПЕРЕД-ПО-ДЕРЕВУ и НАЗАД-ПО-ДЕРЕВУ, если w— дуга дерева обхода, либо операции ВПЕРЕД-ВНЕ-ДЕРЕВА и НАЗАД-ВНЕ-ДЕРЕВА, если w— не дре- весная дуга. --------------------------------- Решение------------ Метод. проц ОБХОД-В-ГЛУБИНУ-1 (р вершина) = 1. S стек дуг = 0; 2. ПОМЕТИТЬ(ро); р := ро, w := ПДУГА(р); 3. пока (tv/ничто) v (8* 0) цикл 4. если tv/ ничто то 5 q := KOHELRtv); 6. если НЕПОМЕЧЕНА(д) то 7 ВПЕРЕД-ПО-ДЕРЕВУ(и); 8 <- w, 8 ПОМЕТИТЬ(д), р := q, w := ПДУГА(д); 9. иначе ВПЕРЕД-ВНЕ-ДЕРЕВА(1У); 10 HASAfl-BHE-flEPEBA(iv); 11. iv := CflyrA(iv) все 12 иначе iv = Э 8; nOCETI4Tb(KOHEL((iv)); 13. если 8 = 0тор := ро 14. иначе р := КОНЕЦ(э S) все; 15. НАЗАД-ПО-ДЕРЕВУ(и); w - СДУГА(и) все все; 16. ПОСЕТИТЬ(ро) все Пусть G— граф, см. рис. 2.47, и пусть ПДУГА(р0) = СДУТА (w,) = ю, ПДУГА(р,) = иь. Тогда при вызове ОБХОД-В-ГЛУбИНУ— 1(ро) выполнение обра- батывающих операций над элементами графа G будет осуществляться в следующей последовательности: ПОМЕТИТЬ(р0), ВПЕРЕД-ПО-ДЕРЕВУ(гц), ПОМЕТИТЬ^), ВПЕРЕД-ПО-ДЕРЕВУ(и4), ПОМЕТИТЬ(р|), ВПЕРЕД-ВНЕ-ДЕРЕВА(и6), НАЗАД- ВНЕ-ДЕРЕВА(г/6), ВПЕРЕД-ВНЕ-ДЕРЕВА(«5), НАЗАД-ВНЕ-ДЕРЕВА(«5), ПОСЕ- ТИТЬ^,), НАЗАД-ВНЕ-ДЕРЕВА(и4), ПОСЕТИТЬ(р2), НАЗАД-ПО-ДЕРЕВУ(М|),
Гпава 2. Ориентированные деревья 121 ВПЕРЕД-ВНЕ-ДЕРЕВА(и2), НАЗАД-ВНЕ-ДЕРЕВА(гь), ВПЕРЕД-ВНЕ-ДЕРЕВА(и3), НАЗАД-ВНЕ-ДЕРЕВA(w3), ПОСЕТИТЬ( р0). А. Пусть q некоторая вершина графа G, достижимая из р0, и wb wr—- после- довательность дуг, исходящих из q. Тогда в процессе выполнения процедуры ОБХОД- В-ГЛУБИНУ сначала помечается вершина q, затем последовательно вперед и назад проходятся дуги wb wr, и лишь затем посещается вершина q. Б. Операция ПОМЕТИТЬ применяется к вершинам графа, достижимым из р0, в по- рядке их первого посещения при обходе в глубину, а операция ПОСЕТИТЬ — послед- него посещения вершин. 2.2.22. Алгоритм обхода графа в глубину с двусторонним прохождением дуг и распределенной реализацией стека --------- Задача----------- Объекты. Упорядоченный ориентированный граф G, каждая вершина которого может находиться в одном из двух состояний ("помечена", "непомечена") и имеет в качестве атрибута СВЯЗЬ имя некоторой дуги. Операции. См алгоритм, разобранный в разд. 2 2.21 Дано. Все вершины графа G, достижимые из заданной вершины р0, непомечены и имеют ничто значением атрибута СВЯЗЬ. Требуется. См. алгоритм, представленный вразд. 2.2.21. ------- Решение--------- Метод. проц ОбХОД-В-ГЛУбИНУ-2 (ро вершина) = 1 v дуга = ничто р вершина = ро 2. ПОМЕТИТЬ(ро); w = ПДУГА( р0); 3. пока (w * ничто) v (v * ничто) цикл 4 если wt ничто то 5. q - КОНЕЦ(ю); 6 если НЕПОМЕЧЕНА(д) то 7 ВПЕРЕД-ПО-ДЕРЕВУ(и/); 8. ПОМЕТИТЬ(д); 9 (q СВЯЗЬ, v, р, iv) = (v, w q, q СВЯЗЬ) 10. иначе BnEPEfl-BHE-flEPEBA(w); 11 НАЗАД-ВНЕ-ДЕРЕВА(и/) 12. iv:=w.CBfl3b все 13 иначе (iv v) - (v, KOHELRv) СВЯЗЬ); 14. ПОСЕТИТЬ(КОНЕЦ(и)); 15 если v = ничто то p := ро
122 Часть I. Обработка и визуализация графов 16. иначе р - КОНЕЦ(у) все; 17 НАЗАД-ПО-ДЕРЕВУ(1У); iv= и-СВЯЗЬ все все; 18. ПОСЕТИТЬ(ро) все Метод основывается на алгоритме, рассмотренном в разд. 2.2.21, и использует для представления стека S атрибут СВЯЗЬ вершин графа: для каждой вершины d дерева обхода значением J-СВЯЗЬ является имя дуги дерева, заходящей в посещаемую вер- шину р, причем v = ничто, если р =р0. В процессе реализации обхода переменная р нигде не используется и может быть удалена из процедуры ОБХОД-В-ГЛУБИНУ-2 (вместе с ее вычислениями), если процедуры прохождения дуг графа не используют имя текущей посещаемой верши- ны. См. свойства, рассмотренные в разд. 2.2.21. 2.2 .23. Алгоритм обхода графа в глубину с двусторонним прохождением дуг и без использования дополнительной памяти --------Задача------------ Объекты. Упорядоченный ориентированный граф G, каждая вершина которого может находиться в одном из двух состояний: "помечена", "непомечена"; атрибут СВЯЗЬ каждого элемента хранит имя некоторого элемента графа G, а атрибут ВЕРШИНА каждой дуги — имя некоторой его вершины. Операции. Помимо операций ПОМЕТИТЬ, НЕПОМЕЧЕНА, ПОСЕТИТЬ, НАЗАД-ПО-ДЕРЕВУ, ВПЕРЕД-ВНЕ-ДЕРЕВА, НАЗАД-ВНЕ-ДЕРЕВА, ВПЕРЕД- ПО-ДЕРЕВУ, описанных в алгоритме (см. разд. 2.2.21), имеется логическая операция СВЯЗЬ-ДУ ГА, которая для элемента F графа G выдает истину, если ЛСВЯЗЬ — это имя дуги. Дано. Все вершины графа G, достижимые из заданной вершины р0, непомечены. Для любого элемента d графа G выполнены свойства: «/.СВЯЗЬ = w, если w— имя первой дуги, исходящей из </, либо w — имя следующей за d дуги, исходящей из той же вершины, что и «/; «/.СВЯЗЬ = ничто, если d— лист, либо d— это последняя дуга в списке исходящих дуг; «/.ВЕРШИНА = q, если дуга d заходит в вершину q. Требуется. См. алгоритм, представленный в разд. 2.2.21 -------- Решение---------- Метод. проц ОБХОД-В-ГЛУБИНУ-3 (р : вершина) = 1. F := ничто; ПОМЕТИТЬ(р0); 2. V :=po, Е - У.СВЯЗЬ;
Глава 2. Ориентированные деревья 123 3. пока (Е т ничто) v (V* р0) цикл 4. если Е * ничто то 5. q - Е.ВЕРШИНА; 6. если НЕПОМЕЧЕНА(д) то 7 ВПЕРЕД-ПО-ДЕРЕВУ(Е); 8. У.СВЯЗЬ := Е; 9. (V, Е, Е.ВЕРШИНА) := (q, V, Е); 10. ПОМЕТИТЬ(У); Е := У.СВЯЗЬ 11. иначе ВПЕРЕД-ВНЕ-ДЕРЕВА(Е); 12. НАЗАД-ВНЕ-ДЕРЕВА(Е); 13. (Е, F, Е.СВЯЗЬ) - (Е.СВЯЗЬ, Е, F) все 14. иначе пока СВЯЗЬ-ДУГА(Е) цикл 15. (Е, F. Е.СВЯЗЬ) := (Е, Е.СВЯЗЬ, Е) все, 16. V. СВЯЗЬ - Е; ПОСЕТИТЬ(У); Е := Е.СВЯЗЬ; 17 (V, Е, Е.ВЕРШИНА) - (Е, Е.ВЕРШИНА, V), 18. НАЗАД-ПО-ДЕРЕВУ(Е); 19. (Е, Е, Е.СВЯЗЬ) := (Е.СВЯЗЬ, Е Е) все все; 20. пока Е* ничто цикл (Е, Е,Е.СВЯЗЬ) := (Е, Е.СВЯЗЬ, Е) все; 21. р0 СВЯЗЬ := Е; ПОСЕТИТЬ(р0) все Приведенная программа написана на основе алгоритма, рассмотренного в разд. 2.2.21, но моделирует стек 5 внутри графа G с использованием атрибутов СВЯЗЬ и ВЕРШИНА. Процедура использует три переменные: V— имя посещаемой вершины, Е— имя проходной дуги, F— так называемая сцепка. Сцепка F определяется по следующим правилам: если Е не является первой дугой, исходящей из И, то F— имя дуги, предшествующей в списке дуг, исходящих из И; если Е— первая дуга, исходящая из К, то F ничто при Г = р0 и F — имя отца верши- ны р в дереве обхода при V*р0. На рис. 2.54 для графа G, представленного на рис. 2.48, указаны его представления непосредственно перед прохождением вперед по древесной дуге (4.5) (рис. 2.54, а) и после (рис. 2.54, б), а также после прохожде- ния дуги (5.2) (рис. 2.54, в), не принадлежащей дереву (в этот момент Е = ничто). А. Для процедуры ОБХОД-В-ГЛУБИНУ-З справедливы свойства алгоритма, рас- смотренного в разд. 2.2.21 Б. В процессе выполнения процедуры ОБХОД-В-ГЛУБИНУ-З обрабатывается ровно два раза каждый элемент списков дуг, исходящих из вершин, достижимых из р0. В. После завершения работы процедуры ОБХОД-В-ГЛУБИНУ-З все элементы графа в качестве атрибутов СВЯЗЬ и ВЕРШИНА имеют те же значения, что и до начала работы процедуры.
124 Часть I. Обработка и визуализация графов Рис. 2.54. Обход графа с двусторонним прохождением дуг
Глава 2. Ориентированные деревья 125 2.2.24. Алгоритм обхода в глубину графа, представленного в виде массива дуг, с двусторонним прохождением дуг графа -------Задача---------- Объекты. Упорядоченный ориентированный граф G, вершины и дуги которого согласованно занумерованы и номера элементов которого могут выступать в качест- ве их имен. Имеется массив ПРЕЕМ длины т, где т — число дуг в G, а граф G рас- ширен изолированной вершиной q0, называемой фиктивной. Каждой вершине q рас- ширенного графа сопоставлены два атрибута: ПД— номер первой дуги, исходящей из q, либо т + 1, если q— фиктивная вершина, и НД— некоторое неотрицательное число, не превышающее числа дуг, исходящих из q. Операции. Для операций ПОСЕТИТЬ, ВПЕРЕД-ПО-ДЕРЕВУ, НАЗАД-ПО- ДЕРЕВУ, ВПЕРЕД-ВНЕ-ДЕРЕВА, НАЗАД-ВНЕ-ДЕРЕВА, описанных в алгоритме (см. разд. 2.2.17), имеется возможность в качестве параметров указывать номера со- ответствующих элементов графа G. Имеется также операция ПОМЕТИТЬ, побочный эффект которой состоит в приписы- вании вершине с указанным номером в качестве атрибута НД числа 1. Дано. Для любой вершины q и дуги w элемент ПРЕЕМ[гг]— это номер конечной вершины дуги w, а <?.НД = 0. Требуется. Для всех вершин q графа G, достижимых из ро, установить атрибут д.НД*О, изменяя нулевые значения атрибута НД вершин на ненулевые в порядке обхода графа G в глубину, начиная с р0, и выполняя над дугами соответствующие операции прохождения. ------ Решение------ Метод. проц ОБХОД-В-ГЛУБИНУ-4 ( р0 : вершина) = 1. р: вершина = 0; q вершина = ро, 2. и/:=ро.ПД; ПОМЕТИТЬ(ро); 3. пока (w < (q + 1) ПД) v(q * р0) цикл 4. если iv < (q + 1).ПД то 5. если ПРЕЕМ[и/].НД = 0 то 6 ВПЕРЕД-ПО-ДЕРЕВУ(и/), 7. q.Hfl:=iv—q.nfl+1; 8. (q, р nPEEM[iv]) := (nPEEM[tv] q, p); 9. w := q.nfl; nOMETHTb(q); 10 иначе ВПЕРЕД-ВНЕ-ДЕРЕВА(и/), 11. НАЗАД-ВНЕ-ДЕРЕВА(уу); iv := w + 1 все 12. иначе nOCETIZITb(q); w = p ПД + р.НД - 1, 13. (q, p, nPEEM[w]) := ( p, nPEEM[w], q);
126 Часть I. Обработка и визуализация графов 14. НАЗАД-ПО-ДЕРЕВУ(м); w := w + 1 все; все; 15. ПОСЕТИТЬ(ро) все Приведенная процедура написана на основе алгоритмов, рассмотренных в разд. 2.2.21 и 2.2.23, при использовании специального представления графа (см. рис. 2.54, г, на котором изображены в виде массива дуги графа G, см. рис. 2.48). Для любой вершины d графа G множество {w : с/.ПД < w < (с?+1).ПД} состоит из но- меров всех дуг, исходящих из d. Процедура ОБХОД-В-ГЛУБИНУ-4 использует три локальные переменные: q — посещаемая вершина, w — проходимая дуга, а также р — отец вершины q в дереве обхода (причем р = 0, если q — корень дерева, т. е. если Ч = Р&~ А. Для процедуры ОБХОД-В-ГЛУБИНУ-4 справедливы свойства алгоритма, см. разд. 2.2.21. Б. В процессе выполнения процедуры ОБХОД-В-ГЛУБИНУ-4 список преемников лю- бой вершины, достижимой из ро, обрабатывается ровно один раз. В. После завершения процедуры ОБХОД-В-ГЛУБИНУ-4 все элементы графа G име- ют те же значения, что и до начала ее выполнения. 2.3. Генерация деревьев Рассматриваются задачи полного и равновероятного порождения деревьев из разных классов: упорядоченных, бинарных, бинарных заданной высоты, Парных, корневых и свободных деревьев. Пусть зафиксирован некоторый класс деревьев D. Тогда ре- шением задачи полного порождения является алгоритм построения последовательно- сти всех элементов из D без повторения, а задачи равновероятного порождения — алгоритм, генерирующий любое дерево из D с одинаковым математическим ожида- нием, равным 1/ |£). 2.3.1. Алгоритм генерации упорядоченных деревьев --------Задача---------- Операции. ВЕЕР(н) по заданному целому числу п строит упорядоченное дерево, состоящее из корня п и листьев 1, 2,..., п — 1 (рис. 2.55). СНИЖЕНИЕ^) применима к любой вершине дерева, имеющей более одного сына, и осуществляет за время 0(1) преобразование, приведенное на рис. 2.56 СЖАТИЕ-ПУТИ(р) делает сыновьями корня все те вершины, которые либо являлись сыновьями вершины р, либо принадлежали пути от корня до р (рис. 2.57), за время О(£), где к — длина пути от корня до р. Н0МЕРА(7) обходит дерево Т в постфиксном порядке и нумерует вершины в поряд- ке их посещения (см. разд. 2.2.17).
Гпава 2. Ориентированные деревья 127 Рис. 2.55. Результат выполнения операции ВЕЕР(г) Рис. 2.56. Результат выполнения операции СНИЖЕНИЕ(р) Рис. 2.57. Операция СЖАТИЕ-ПУТИ(р) Дано. Целое число и. Требуется. Сгенерировать все упорядоченные деревья с и вершинами. -------- Решение---------- Метод. проц СЛЕДУЮЩЕЕ-ДЕРЕВО (7 дерево) = 1 . р = КОРЕНЬ(Т); 2 . если ЧИСЛО-СЫНОВЕЙ(р) > 1 то 3 . СНИЖЕНИЕ(р)
128 Часть I. Обработка и визуализация графов 4 иначе цикл р = СТАРШИЙ-СЫН(д) 5 до ЧИСЛО-СЫНОВЕЙ(р) > 1 все 6 СНИЖЕНИЕ(р); 7 СЖАТИЕ-ПУТИ(р) все все; проц ГЕНЕРАЦИЯ (л цел) = 1. Г-ВЕЕР(л); 2. НОМЕРА(Т); 3 % дерево построено % 4. для к от 2 до Ьп цикл 5 СЛЕДУЮЩЕЕ-ДЕРЕВО(Т); 6. % дерево построено % все все (0,1.0) Ю.1.1) (0.1,2) (0,2.0) Рис. 2.58. Последовательность генерируемых деревьев
Глава 2. Ориентированные деревья 129 В процедуре ГЕНЕРАЦИЯ через Ь„ обозначено количество упорядоченных деревьев с п вершинами (см. разд. 2.1.4). Заметим, что процедура СЛЕДУЮЩЕЕ-ДЕРЕВО невыполнима, если Т—линейное дерево (см. цикл 4—5 процедуры ГЕНЕРАЦИЯ). Однако ошибки здесь не возникает, поскольку линейное дерево всегда генерируется последним. Рассмотрим следующий пример. На рис. 2.58 приведена последовательность всех деревьев, генерируемых при обращении к процедуре ГЕНЕРАЦИЯ с п = 5. Рядом с деревьями указаны их коды (<72, dy, di), где d,— число сыновей вершины с номером /. Стрелка указывает на преобразуемую вершину. А. Средняя длина всех сжимаемых путей не превышает 11/16. Б. Среднее время, затрачиваемое процедурой ГЕНЕРАЦИЯ на построение одного дерева, равно О( 1). 2.3.2. Алгоритм генерации бинарных деревьев --------Задача---------- Операции. ЛЕВОЕ-ЛИНЕЙНОЕ-ДЕРЕВО(н) строит левостороннее дерево, состоя- щее из п вершин. ПРАВАЯ-РОТАЦИЯ(р) осуществляет преобразование, представленное на рис. 2.59. ПОЗИЦИЯ^, Т) выдает вершину, занимающую к-ю позицию в пути по дереву Т от его корня к самому левому листу. ЛЕВАЯ-РОТАЦИЯ(<?) осуществляет переход от дерева, представленного на рис. 2.59, б. к дереву рис. 2.59, а. Рис. 2.59. Преобразование ротации Дано. Целое число п. Требуется. Сгенерировать все бинарные деревья с и вершинами. ------Решен и е----- Метод. проц ПРОВЕРКА^: цел, Т: дерево, R: вектор) = 1. (m,/) =(n-fc-R[fc+1], 0); 5 Зак. 202
130 Часть I. Обработка и визуализация графов 2. пока 1<т цикл 3. если / * 0 то ПРАВАЯ-РОТАЦИЯ(ПОЗИЦИЯ(к, Т)) все; 4. (R[R], Г) := (R[k + 1] + I, /+1); 5. если к - 1 то 6. % дерево построено % 7 иначе ПРОВЕРКА^ - 1, Т, R) всв все; 8. % восстанавливвется позиция к дерева % 9. цикл m раз ЛЕВАЯ-РОТАЦИЯ(ПОЗИЦИЯ(к, Г)) все всв; проц ГЕНЕРАЦИЯ (л цел) = 1. R массив = {(>,0)./е [/: л]}; 2. Т := Л ЕВОЕ-ЛИНЕЙНОЕ-ДЕРЕВО(л); 3. ПРОВЕРКАМ - 1, Г, R) все Проанализируем работу процедуры с точки зрения генерации ротационных кодов (см. разд. 2.1 13) соответствующих генерируемых ею деревьев. Пусть 2Г= (х„_|, -, х2, Х|) обозначает ротационный код дерева Т. Процедура осуществляет генерацию всех ротационных кодов в лексикографическом порядке, основываясь на стратегии возвратного хода. Дерево возвратного хода для л = 4 приведено на рис. 2.60; пометки дуг от корня к листьям изображают значения х3, хг, х, в соответствующем порядке. Пометка любой вершины — это то значение, которое присваивается элементу /?[А] после того, как в кодовом слове заполнен элемент хк. Нетрудно видеть, что /?[/: + 1]— это суммарное количество правых ротаций, выполненных до заполнения хк, те R[k+ 1] =x„-i + x„+2 + ... +д>+|, ат— максимальное значение, допустимое для хк. Нетрудно модифицировать процедуру таким образом, чтобы она генерировала толь- ко ротационный код всех полных бинарных деревьев. Рис. 2.60. Дервво возвратного хода
Глава 2. Ориентированные деревья 131 А. Каждый из операторов, образующих тела циклов 2—7 и 9, выполняется 2а„ раз, где 1 (2п\ а„ = --7 — и + 1< пJ количество бинарных деревьев на п вершинах. Б. Среднее время, затрачиваемое процедурой ГЕНЕРАЦИЯ на построение одного дерева, равно О( 1). В. 2(п — 1 )(п + 2) — среднее число ротаций при построении одного дерева. 2.3.3. Алгоритм генерации бинарных деревьев заданной высоты ---------Задача----------- Объекты. Бинарные деревья Т фиксированной высоты h, представленные в виде T=(N, М,А) (рис. 2.61). Это представление базируется на поуровневом позиционном коде Ли (см. разд. 2.1.3). Дерево Т состоит из компонент N, М и А, имеющих сле- дующий смысл: W— вектор 7V[1], 7V[2], ..., N[h] распределения внутренних вершин по уровням, где — это количество внутренних вершин дерева Т, расположенных на уровне Л; М—последовательность, полученная из N = Ml; М2;...; Mh, где Mi = ЛЛ[1], М/[2],..., ЛЛ[[ М ][/]] — вектор позиций расположения внутренних вершин на уровне /, путем удаления векторов Mi для полностью заполненных уровней i, т. е. при переходе от [ М ] к Л/удаляется вектор М\, а также все такие векторы Mi, что 7VJ7] = 2N[i — 1]; А — вектор номеров А[ 1 ], А[2], ..., А[1] не полностью заполненных уровней дерева, где / — это количество не полностью заполненных уровней для дерева Т, а Л[/] — это <-й (в порядке их рассмотрения снизу вверх) не полностью заполненный уровень дерева. На рис. 2.61 изображено бинарное дерево, для которого h = 6; N~ 1,2, 3, 2, 4, 1; М= 1,2,4; 3, 5; 4; полностью заполнены уровни 1, 2 и 5; А = 1, 3, 4. Рис. 2.61. Бинарное дерево
132 Часть I. Обработка и визуализация графов Свойства. Для любого дерева Т= (N, М, А): Л'[1] = 1, 1 <Лфй + I] < 2)V[£] для каж- h дого k, 1 < к < й; У 7У[й] = п, где п — число внутренних вершин дерева Т. к=1 Дано. Целые числа п и И. Требуется. Сгенерировать все бинарные деревья с п внутренними вершинами и с высотой, не превышающей й, в такой последовательности T\ = (N\, Mt, Л,), Г2 = (М, М2, А2),..., Т, = (N„ Mt, А,),..., что для любых / и j, если i < j, то высота 7, пре- вышает высоту Tj или Т, и Tj совпадают по высоте и либо N, лексикографически предшествует Nj, либо N, = N/ и Л/, лексикографически предшествует М}. ------Решение------- Метод. функ НАЧАЛЬНОЕ-Л/(л, к цел) = 1. еслил<йто 2. возврат (1П, 0к-п) 3. иначе г := тах{/: (л - к) > 2' - / - 1 }; 4. m = (п - к) - (2Г-г- 1); 5. возврат (1*Л 2°, 21,.... 2Г1) Ф НАЧАЛЬНОЕ-Л/(т, г) все все; проц СЛЕДУЮЩЕЕ-Л/ (N вектор; л, к цел) = 1. /=тах{/ 1<к, Л/[/]^ 1, Л/[/]*2Л/[/- 1]}; 2. % если N не лексикографический максимум, то / > 1 % 3. m:= £л/[Д-1; 4. Л/[/] := Л/[/] + 1; 5. для у от / до к-1 цикл 6. г=тах{/ т><2(*“Л-1)}; 7. Л/[/+1]=г+1; 8. пг=т- Л/[/] все все; проц СЛЕД-ДЕРЕВО (М, N, A, D вектор) = 1. k =min{/ к 2. р = ДЛИНА(М) - J/V [А[/11 + О[/1 -1; >1 з. /и[р] = Ир] +1; 4. (Q, р1) • = ( р+ N [А[й]] - D[k], р + 1); 5. если D[Aj * Л/[А[й]] то 6. если/И[р1] -/И[р] = 1 то 7. О[А] - D[k] - 1
Глава 2. Ориентированные деревья 133 8 иначе О[/<] = Л/[А[к]] 9. пока р1 < q цикл 10 (/И[р1] р, р1) = (М[р1] + 1, р1, р + 1) все все 11 . иначе если М[р] - 2 Л/[А[к] - 1] то 12 D[R] := D[A] - 1 все все; 13 . р=д+1, 14 . для । от к - 1 до 1 шаг — 1 цикл 15 для у от 1 до Л/[А[/]] шаг 1 цикл 16 . (М[р], р) - (/, Р + 1) все; 17 D[/] '= Лф4[|]] все все; проц ГЕНЕРАЦИЯ^, h цел) = 1. для к от h шаг — 1 до Г/од2 (л + 1) 1 цикл 2. N = НАЧАЛЬНОЕ-Л/(л, к); 3. ДЕРЕВЬЯ-ДЛЯ-Л/ начало 4. Вычислить по N лексикографически минимальное [ М ] и построить по N и М массивы М, А и D; 5. % дерево построено % 6 пока М не лексикографический максимум цикл 7 СЛЕД-ДЕРЕВО(Л/, М, A, D); 8. % дерево построено % все; 9. если N не лексикографический максимум то 10 СЛЕДУЮЩЕЕ-Л/(Л/, л, к); 11. начать ДЕРЕВЬЯ-ДЛЯ-Л/ все конец все все Функция НАЧАЛЬНОЕ-N— это рекурсивный алгоритм вычисления лексикографи- чески минимального N для заданных п и к, например, для п = 24 и к = 6 имеем НАЧАЛЬНОЕ-Л/ (24,6) = (1, 1, 1, 2, 4, 8) ® НАЧАЛЬНОЕ-Л/ (7,4) = = (1, 1, 1, 2, 4, 8) © (1, 1, 1, 2) © НАЧАЛЬНОЕ-Л/(2, 2) = = (1, 1, 1,2, 4, 8)®(1, 1, 1,2)®(1, 1) = = (1, 1, 2, 3, 6, 11). Процедура СЛЕДУЮЩЕЕ-N по некоторому N, не являющемуся лексикографически максимальным для заданных пик, вычисляет в N лексикографически следующее
134 Часть I. Обработка и визуализация графов за А распределение и вершин по к уровням бинарного дерева. Здесь i— это первая справа позиция элемента в N, поддающегося увеличению, ат — количество вершин дерева, которые нужно распределить по к - i уровням, расположенным ниже i, после увеличения числа вершин на i-м уровне (оператор 4). Оператор цикла 5—8 строит в 7V[7 + 1], N[i + 2], ..., МЛ] лексикографический минимум, проблема построения ко- торого аналогична решаемой вызовом HA4AJIbHOE-/V(w, Л - 1) с тем отличием, что первый элемент (А[г + 1]) не должен быть обязательно равен единице. Процедура СЛЕД-ДЕРЕВО работает с деревом 7’ в терминах векторов Л/, 7V, А и £>, где D— вектор, используемый для указания на те крайние справа позиции вершин в М, которые можно перемещать вправо, не нарушая распределения N ; £)[Л] = 0, если все вершины на уровне А[к] расположены в крайних справа позициях, и равно пози- ции первой справа перемещаемой вершины на уровне А[к] иначе (заметим, что по- добно индексам массива А индексы массива D — это номера не полностью заполнен- ных уровней дерева, занумерованных снизу). Например, при N = 1,2, 3, 2, 4,1 и А = 1, 3, 4 имеем D = 1, 1,2 для М= 1, 2, 4; 3, 6; 1 и D = 0, 1,2 для Л/ = 1, 2, 4; 3, 6; 8. Резуль- татом работы процедуры СЛЕД-ДЕРЕВО является перевычисление М и D, соответ- ствующее переходу к дереву Т'= (N, М, А), которое по условию задачи должно быть сгенерировано вслед за Т. Рассмотрим процедуру СЛЕДЕРЕВО более детально. В ней Л [Л]— уровень, ар- позиция вершины в М, которая должна быть сдвинута вправо на одну позицию при переходе к Т'. Этот сдвиг осуществляется оператором 3. Затем (строки 4—17) осуще- ствляется размещение в левые позиции всех вершин, которые расположены за вер- шиной р на уровне А[к] (операторы 4—12), и всех вершин с уровнем Л[г], 1 < i < к (операторы 4—17), с соответствующим изменением D\ q— это позиция в М самой правой вершины уровня А[к]. Условие 5 проверяет, не является ли текущая вершина самой правой на этом уровне, а условие 11 — становится ли текущая вершина самой правой. А. Алгоритм затрачивает в среднем на генерацию одного дерева 0(1) времени 2.3.4. Алгоритм генерации k-арных деревьев ---------Задача------------ Дано. Целые числа к и п. Требуется. Сгенерировать всеи-вершинныеЛ-арные деревья. -------Р е ш е н и е------- Метод. проц ГЕНЕРАЦИЯ (л : цел к : цел) = 1. для всех / из [1 : л] цикл В[/] := (Л-1) * n + i все; 2. % код построен % 3. пока В * (к, 2 х к, .... л х к) цикл 4. Пусть j — максимальное целое, для которого В[/] > к х j и В[/] > E\j — 1] + 1 (предполагается, что В[0] = 0)
Гпава 2. Ориентированные деревья 135 5. В[/]:=В[/]-1; 6. для всех / из [/+ 1,л] цикл 7. ВД:=(к-1)хл + 1 все; 8 % код построен % все все Алгоритм генерирует последовательность j'-кодов Закса Парных деревьев с и верши- нами (см. разд. 2.1.3) в порядке, обратном лексикографическому. А. Среднее время генерации кода одного дерева составляет 0(1). 2.3.5. Алгоритм генерации корневых деревьев -------------------------------- Задача------------ Дано. Целое число и. Требуется. Сгенерировать все корневые деревья с п вершинами. --------------------------------Решение------------ Метод. проц КОРНЕВЫЕ-ДЕРЕВЬЯ (л: цел) = 1 L.= (1,2.л); 2. если л < 2 то р := 1 иначе р := л все; 3. Р:=(1 2, ...,р- 1, 0. 0.0); 4. S:=(0"); 5. % первое дерево построено % 6 пока р > 1 цикл 7. Цр]-Цр]-1; 8. если (р < л) л ((Ц р] 2) v (L[p - 1] * 2)) то 9. d:=p-P[L[p]J; 10. пока р < л цикл 11. (S[p], P[L[ р]], р) := (Р[Цр]], р, р + 1); 12 L[p] := L[p - d] все все; 13. пока L[p] = 2 цикл 14 р.= р-1; 15. P[L[p]] := S[ р] все; 16. % следующее дерево построено % все все
136 Часть I. Обработка и визуализация графов В процессе работы алгоритма происходит многократный переход от текущего кано- нического уровневого кода L к коду s(L) таким образом, что генерируются все кано- нические уровневые коды в лексикографически убывающем порядке, начиная от ко- да [1,2,..., п] и заканчивая кодом [1, 2, 2,..., 2]. Пусть L = [Д, /„] * [1,2,2,..., 2] и пусть р = тах{Л : Д > 2} и q = тах{А:: к< р и /* = Iр — 1} Тогда s(L) = [sb s„], где S/ = /, для всех /е[1, р) и s, = s,-(P-q} для всех i е [р, и] (см. табл. 2.4). Таблица 2.4. Уровневые коды корневых деревьев L s(L) [1,2, 3, 2, 2, 2] [1,2, 3, 4, 2, 2] [1,2, 3,4, 3, 2, 2, 2, 2, 2, 2, 2] [1,2, 3, 4, 5, 5, 2, 2, 2, 2] [1,2, 2, 2, 2,2] [1,2, 3,3, 3,3] [1,2, 3, 4, 2,3,4, 2, 3, 4, 2, 3] [1,2, 3, 4, 5,4, 5, 4, 5,4] Отношение между L и s(L) схематично можно изобразить следующим образом: L = [lh ...,1ч,...,1рЧ,1р, 2,2, ..., 2] s(L) = [h,..., lq, —, Ар •••] тч т„ ' Т " В процедуре КОРНЕВЫЕ-ДЕРЕВЬЯ вектор L хранит текущий код, вектор Р исполь- зуется для быстрого нахождения q по заданному р, а вектор S— для быстрого изме- нения вектора Р. А. Среднее время генерации одного дерева составляет 0(1). 2.3.6. Алгоритм генерации свободных деревьев ---------Задача------------ Дано. Целое число п. Требуется. Сгенерировать без повторения все неизоморфные свободные деревья с числом вершин п. ---------Решен и е--------- Метод. проц СЛЕД-ДЕРЕВО (L, W вектор п р. q hl h2, с г:цел) = 1. ф:=ложь; 2. если (с = л + 1) v (р = Р2)л((ЦР1] = L[h2] + 1) л (л = 62 > г- Л1) v vL[M] = L[h2])K(n-h2 + 1 <r-h1)) 3 то если L[r] > 3 то 4 (р, Q) .= (г, W[rJ);
Гпава 2. Ориентированные деревья 137 5. если hi = г то hi := h - 1 все; 6. ф = истина; 7 иначе (р, г, q) = (г, г- 1, 2) все все; 8. нужно_г, нужно_с нужно_Л2) := (ложь, ложь, ложь); 9. если р < Л1 то Л1 := р -1 все; 10. если р < гто нужно_г := истина 11. иначе если р < Л2 то нужно_Л2 = истина 12. иначе если (L[/?2] = L[h1] - 1) л (л - Л2 = г-М) 13. то если р < с то нужно_с := истина все 14. иначе с := П все все все; 15. (стар_р, 5, стар_/ц, стар_и/ц, р) := (р, q-p, L[q], W[q], 5); 16 для i от стар_ р до л цикл 17. Ц/1 :=(.[/ + 8]; 18. если Lp] = 2 то Wp] := 1 19. иначе р := /; 20. если Lp] = стар_/р то q = CTap_wq 21. иначе q:=Wp + 8]-8 все; 22. W[/] := q все; 23. если нужно_гл (Lp] = 2) то 24. (нужно_г, нужно_Л2, г) := (ложь, истина, i — 1) все; 25. если нужно_Л2 л (Lp] < Lp — 1 ]) л (/ > г + 1) то 26. (нужно_Л2, h2) := (ложь, /- 1); 27. если (L[A>2] = L[M] — 1) л (л — h2 = г— М) то 28. нужно_с := истина 29. иначе с := Q все все; 30. если нужно_с то 31. если Lp] ЦЛ1- Л2 + /] - 1 то 32. (нужно_с, с) := (ложь, /) 33. иначе с := / + 1 все все все; 34. если ф то 35. г:=л-Л1+1;
138 Часть I. Обработка и визуализация графов 36. для i от г+ 1 до п цикл (£[/], W[/J) := (/- г + 1, /- 1)все; 37 (W[r+ 1], h2, р, q, с) := (1,л, л, р—1.П) 38. иначе если р = П то 39. если Цстар_р -1 * 2 то р := стар_ р-1 40. иначе р := стар_р-2 все; 41. q:=\N[p] все; 42. если нужно_й2 то 43. Л2 := л; 44. если (Цб2] = £[Л1]- 1) л (Л1 = г) то с := л + 1 45. иначе с := П все все все все; проц СВОБОДНЫЕ-ДЕРЕВЬЯ (л : цел) = 1. /<:=1л/2 J+1; 2. £ := (1,2,.... fc, 2, 3, ... л-к+1); 3. W ;= (0, 1.к- 1, 1, к + 1.л- 1); 4. если л = 4 то р := 3 иначе р := л все; 5. (q, Л1, Л2, г) := (п-1, к, п, к); 6. если нечетное л то с := О иначе с := п + 1 все; 7. % дерево сгенерировано % 8. пока q т 0 цикл 9. СЛЕД-ДЕРЕВО(£, W, л. p,q,h1, 62, с, г) 10. % дерево сгенерировано % все все В основу данного алгоритма положен алгоритм генерации корневых деревьев, рас- смотренный в разд. 2.3.5. В процессе работы процедуры СВОБОДНЫЕ-ДЕРЕВЬЯ осуществляется генерация всех главных канонических уровневых кодов и- вершинных свободных деревьев (см. разд. 2.1.3) с использованием процедуры СЛЕД- ДЕРЕВО, реализующей определенную модификацию функции .s- (см. разд. 2.3.5). Здесь L и W— целочисленные векторы длины п; в L хранится канонический уровне- вый код L*(T, z) текущего дерева (Т, z), а в W[i] — индекс элемента в L, соответст- вующего в дереве (Т, z), отцу вершины, представленной элементом £[/]; р — это наи- больший индекс такой, что £[р] Ф 2, a q— это наибольший из индексов, для которых q < р и L\q}= L[p\ - 1. £ можно рассматривать как уровень корня z (а именно уровень 1), сцепленный с уровневыми кодами каждой из компонент, получающихся после удаления z из Т. Эти уровневые коды компонент называются основными подпоследовательностями £, начинаются с уровня 2, а не 1, но в другом являются каноническими уровневыми кодами, причем они упорядочены в £ по высоте, hi— это наименьший индекс нам-
Глава 2. Ориентированные деревья 139 большего значения уровня в /-й основной подпоследовательности L, a m— первая позиция второй основной подпоследовательности. Таким образом, £[£!] — 2— это высота первого поддерева дерева (7, z), а £[Л2] — 2— высота второго, причем z — единственный центр Т при £[/г1] = £[А2] и Т является бицентральным при £[А1] = £[Й2] — 1. Кроме того, L является главным каноническим уровневым кодом тогда и только тогда, когда справедливы следующие свойства: (О £2 (и, следовательно, ш) существует; (п)£[Л2]>£[А1]- 1; (Hi) если в (н) равенство, то т - 2 < п - т - 2; (л>) если в (ш) равенство, то для 1Л = [£[2] - 1, £[3] - 1,..., L[m - 1] - 1] и L2 = [£[ 1], L[m], L[m + 1],..., £[н]] имеем: L\ = £2 или £1 короче £2, или £1 и £2 имеют одну и ту же длину, но £1 лексикографически предшествует £2. с — это первый элемент из £2, который отличен от соответствующего ему элемента в£1, аг - т — 1. В процедуре СВОБОДНЫЕ-ДЕРЕВЬЯ цикл 8—10 работает до тех пор, пока не будет построен код £ = [1, 2, 2,..., 2]. Значение с устанавливается равным О, если оно не требуется на следующей итерации. А. Алгоритм занимает О(п) памяти и в среднем тратит на построение одного де- рева О( 1) времени. Б. Алгоритм генерирует все основные канонические уровневые последовательности в их лексикографическом упорядочении. 2.3.7. Генерация равновероятных деревьев Существуют три подхода (генерация по номеру, по времени и прямая генерация) к генерации равновероятных деревьев, каждый из которых основывается на датчике равновероятных чисел. Пусть зафиксирован некоторый класс деревьев D и пусть d = |£)|. Первые два подхода предполагают рассмотрение некоторого линейного упорядоче- ния на£), позволяющее связать с каждым деревом Т е D его номер п(Т). Генерация по номеру (см. разд 2.3.9) состоит из двух шагов: генерация равновероят- ного номера г дерева из £); построение дерева Т, для которого п(Т) = г. Генерация по времени предполагает использование алгоритма полной генерации £), последовательно порождающего деревья из D в соответствии с заданным линейным упорядочением (например, одного из алгоритмов, рассмотренных в разд. 2.3.1 — 2.3.8), и состоит из двух шагов: генерация равновероятного времени t на применение алгоритма полной генерации; использование алгоритма полной генерации деревьев из D до тех пор, пока не исчерпается время £ Прямая генерация (см. разд. 2.3.8) означает непосредственное построение случайного дерева в неупорядоченном множестве D.
140 Часть I. Обработка и визуализация графов Из-за ограниченности длины машинного слова в реальных ЭВМ существующие дат- чики случайных чисел генерируют лишь конечное множество чисел, число которых может оказаться меньше d. Поэтому во всех предлагаемых подходах случайное дере- во (неважно, явно или неявно: через его номер или время, необходимое на его поро- ждение алгоритмом полной генерации) выделяется на основе некоторой конечной последовательности (£ь..., ..., ^/), где I > 1. Элемент этой последовательности сужает D до одного из подмножеств d\, ..., D] образующих разбиение D, сужает полученное подмножество аналогичным образом и т. д., а приводит к некоторому подмножеству, состоящему из одного дерева, построение которого считается резуль- татом генерации случайных деревьев. При этом необходимо, чтобы последователь- ность (£ь ..., ..., ^/) обладала следующими свойствами: равной вероятностью для каждого и независимостью событий между собой. 2.3.8. Алгоритм прямой генерации равновероятных упорядоченных корневых деревьев -------Задача-------- Операции. СЛУЧАЙНОЕ-ЧИСЛО— датчик равновероятных вещественных чисел Дано. Целое число п. Требуется. Сгенерировать равновероятное н-вершинное упорядоченное корневое дерево. ------Решен и е---- Метод. функ СЛУЧАЙНОЕ-ДЕРЕВО (л : цел) = 1. (В[1], В[2хл-2],у):=(1,0, 1); 2. для / от 1 до л - 2 цикл 3. := СЛУЧАЙНОЕ-ЧИСЛО; 4. а:=0 + /)х(у + /-1)х(/-1)/(2х;х(2х/-1) х (/-1)); 5. если £ < а то 6. (В[2 х/], В[2 х/ + 1], у) := (1, 1.J+1) 7. иначе р := (/ + у) х (/ - у)/ ((/- 1) х (2 х /- 1)); 8. если < a + р то 9. (В[2 х/], В[2 х/+1]) := (1, 0) 10. иначеу:=2хр; 11. если £ < a + у то 12. (В[2 х/], В[2 х/+1]) := (0, 1) 13. иначе (В[2 х /], В[2 х I + 1],у) := (0, 0,у- 1) все все
Гпава 2. Ориентированные деревья 141 все все; 14. возврат В все Вектор В длины 2(л- 1) используется для хранения генерируемого дерева, представ- ленного в виде двоичного кода с дублированием вершин (рь р2, Д»-2), который образуется путем обхода в глубину дерева, когда всякий раз при увеличении рас- стояния от корня записывается "1", а при уменьшении — "О" (см. разд. 1.2.9). Следует заметить, что некоторая двоичная последовательность (рь р2,р2„_2) является ко- дом указанного вида тогда и только тогда, когда • Pi=l, • Рзл-2 = О, 2 л-3 * И 1=1 2Л-1 • Уд > i для любого к е [2 ; и). i=I Построение кода в В состоит из вычисления В[1] и В[2п - 2] (оператор 1), за которым следует и - 2 шага, на каждом из которых генерируется одна из пар "00" (опера- тор 13), "01" (оператор 12), "10" (оператор 9) или "11" (оператор 6). Здесь а = | | /1 |, P = |D^_I7|/|D,mj|, где для любых z и j через £);/ обозначается множество деревьев с п вершинами, у ко- торых в начальном зафиксированном отрезке кода единиц на j больше, чем нулей, а оставшийся непостроенный (различающий их) отрезок имеет длину 2z - 1 (т. е. оста- лось выполнить z — 1 шаг в процессе построения результирующего дерева). Другими словами, построение кода случайного дерева В можно интерпретировать как последовательное выполнение п - 2 шагов, на каждом из которых множество DtJ сужается до одного из множеств (£),_/, О,_| , и ZZ>,17_i), что соответствует записи в В одной из пар: 1) "00", 2) "01" либо "10", 3) "11". Всевозможные последовательности таких шагов можно рассматривать на плоскости с целочисленными координатами (см. рис. 2.62 для случая и = 6). При этом — это количество различных путей из точки (z,y) в точку (1, 1). Например, при и = 6 и последовательности случайных чисел 0,75; 0,47; 0,19; 0,89 по- лучается путь D5 [ ——> О42 —£>3 2 —00. _> D21 —> £>и, которому соответ- ствует код 1110100100. Данный алгоритм можно использовать для генерации равновероятных деревьев из других классов, определяя подходящие взаимно однозначные соответствия между
142 Часть I. Обработка и визуализация графов классом упорядоченных корневых деревьев и другими классами. Например, функция g(P), которая заменяет в последовательности р каждую цифру "1" на "2", задает вза- имно однозначное соответствие между кодами упорядоченных корневых деревьев и кодами бинарных деревьев (рис. 2.63). Свойство. Алгоритм занимает О(п) времени и О(н) памяти. Рис. 2.62. Представление последовательности шагов генерации Рис. 2.63. Соответствие между кодами деревьев 2.3.9. Алгоритм генерации по номеру равновероятных k-арных деревьев -------Задача-------- Операции. Л К'-' )/(*-!)]/ • /, I + J -1) _ 'у (l + J - КГ j-r J 77 I
Глава 2. Ориентированные деревья 143 Для любых к, пи I значение W((A-l)n - / - 1, п, к~)— это количество различных таких и-кодов Ли (см. разд. 2.1.3) Л-арных «-вершинных деревьев, которые начинаются с 0/+|, т. е. с последовательности нулей длины /+1. Дано. Целые числа n,kwt. Требуется. Сгенерировать Л-арное «-вершинное дерево Т, и-код Ли, который в ан- тилексикографическом упорядочении является t-ы. по порядку (обозначаем / = индекс(Т)). ---------р е ш е н и е------- Метод. функ ДЕРЕВО_ПО_НОМЕРУ(к, л, f: цел) = 1 (a, j) := (Г, л), 2. цикл Найти такое что H(lj, j, к) < а < Н(( + 1, j, к)\ 3 (a.j) =(t-H(lj.j, к), j- 1) 4. до а = 1 все; 5 %f=1+ ^H(ljJ,k)% hio+'> 6. (A, m) := ((0(М) * ;о, 1 о) Уо + 1); s := (R - 1) * m - /т; 7 ПОВТОР: начало 8. (A[s + 1], A[s + 2],. .. A[k * т]) := (A[s- к + 1], A[s- к + 2],.... А[/с * (т - 1)]); 9. (A[s-k + 1], A[s- к + 2], .... А[з]) := (О*-1, 1); 10 т := т + 1; 11. если m < л то 12. s := (к- 1) * т -/т; начать ПОВТОР все конец; 13 возврат(0. А) все Операторы 1—4 осуществляют декомпозицию / (она единственна) такую, что /=1+ ^Я(/7,7Л). >=/«+ Заметим, что для а = (0z Ip) g а(к, «), где а(к, л)— множество последовательностей, полученных из «-колов Ли ft-арных л-вершинных деревьев удалением первого нуля, имеем: индекс(а) = 1, если п = 0 (т. е. а — пустая последовательность); индекс(ос) = Н((к - 1)« -1 - 1, п, к) + индекс(0/-А+1 Р), если п > 0.
144 Часть /. Обработка и визуализация графов Операторы 6—12 строят код Ли с конца: начиная с ((/* l)'°, I7") е а(/0, А) в него вставляются последовательности О*-11 для получения элементов из a(j0 + 1Д), a(j0 +2, k~),a(n, k). В качестве примера рассмотрим случай а е а(3,3), когда индекс(а) = 8. После опера- торов 1—4 имеем 8 = //(2,3,3) + //(0,2,3) + 1. Оператор 6 присваивает А последовательность (001). Операторы 8—9 изменяют А на (000101) — вставкой 001 после первого нуля, а затем — на (000100101). Результатом функции является код (0000100101) дерева, изображенного на рис. 2.64. Рис. 2.64. Результирующее дерево А. Время работы алгоритма составляет O(max((« log ri)/k, kri)), причем (п log n)/k в этом выражении связано с осуществлением декомпозиции t (оператор цикла 2—4). 2.4. Каркасы Задача о построении каркасов графов возникает достаточно часто в различных при- ложениях, например, при планировании очередности пропуска задач для минимиза- ции обращения к памяти, а также входит как вспомогательная при решении более сложных задач. Эти задачи хорошо известны, их постановки и методы решения встречаются практически в каждой книге по теории графов и их приложениям. 2.4.1. Задача об отыскании оптимального каркаса Оптимальным каркасом взвешенного графа G называется каркас, минимизирующий некоторую функцию от весов входящих в него ребер. Чаще всего в качестве такой функции выступает сумма весов ребер, реже— произведение, еше реже— произ- вольная сепарабельная функция. Оптимальный каркас еще называют кратчайшей связывающей сетью для данного графа.
Глава 2. Ориентированные деревья 145 Нахождение каркасов в обыкновенных графах Приводимые два алгоритма являются вариантами поиска в глубину и ширину Алгоритм 2.1. Нахождения каркаса на основе поиска в глубину Дано. Связный граф G(K, Е), заданный списками смежности ЗАПИСЬ^], ve К Требуется. Каркас (И, Т) графа G. Метод. ' проц KAPKAC1(G граф v вершина) = 1. HOBblLi[v] := ложь; 2. для и е ЗАПИСЬ[У| цикл 3. если НОВЫЙ[и] то % (v.u) — новое ребро % 4. Т:= ru{(v,U)}, 5. KAPKAC1(u); все все, начало 6. для и е V цикл НОВЫЙ[v] := истина все; 7. Т := 0 % Т ~ множество найденных к этому моменту ребер % 8 КАРКАС1(г) % г— произвольная вершина графа % все конец Алгоритм 2.2. Нахождения каркаса на основе поиска в ширину Дано. Связный граф G = (И,£), представленный списками смежности ЗАПИСЬ[г], v eV. Требуется. Каркас (К, Т) графа G. Метод. проц КАРКАС2 (G : граф; v: вершина) = 1 . для и е I/ цикл НОВЫЙ[ц] := истина все; % инициализация % 2 . Т:=0; % Т— множество найденных к этому моменту ребер % 3 ОЧЕРЕДЬ = 0; ОЧЕРЕДЬ <= г, 4 НОВЫЙ [г] := ложь; % г— корень каркаса % 5 . пока ОЧЕРЕДЬ * 0 цикл 6 . v <= ОЧЕРЕДЬ; 7 для и е ЗАПИСЬ[и] цикл 8 если НОВЫЙ[ц] то % (v, и) — новое ребро % 9 ОЧЕРЕДЬ <= о; 10 НОВЫЙ [и] := ложь;
146 Часть I. Обработка и визуализация графов 11. Г:=Ги(у, и) все все все все Алгоритм Краскала Содержательно данный алгоритм представляет собой следующую последователь- ность шагов. HI аг 1. Начать с вполне несвязного графа Т, содержащего п изолированных вершин, где п есть число вершин исходного графа G. Ш а г 2. Упорядочить ребра графа G в порядке неубывания их весов. Шаг 3. Начав с первого ребра в этом списке, добавлять ребра в графе Т, соблюдая условие: такое добавление не должно приводить к появлению цикла в Т. LU а г 4 Повторять шаг 3 до тех пор, пока число ребер в Т не станет равным п — 1. Получившееся дерево является оптимальным каркасом графа G. Наиболее трудоемким является шаг 2: для графа с m ребрами нужно выполнить по- рядка m log2w операций, чтобы составить полный список ребер в порядке возраста- ния их весов. Однако полный список не требуется, т. к. весьма правдоподобно, что п— 1 допустимых ребер, образующих оптимальный каркас, будут найдены после просмотра только "верхней" части списка, содержащей г < m ребер. Отсюда немед- ленно следует, что процедура сортировки, используемая на шаге 2, должна быть про- цедурой многократного обращения, дающей корректное расположение первых р ре- бер в конце р-го цикла обращения. Это потребует только г log2 m операций. Тем не менее использование алгоритма Краскала эффективно для графов с малым числом ребер. Рассмотрим более формализованный вариант алгоритма Краскала. Пусть G = = (V, Е) — неориентированный граф с функцией стоимости с, заданной на его ребрах. Требуется построить оптимальный каркас Г=(И, S). Пусть ES— набор непересе- кающихся множеств вершин. Каждое множество W из VS представляет собой связное множество вершин, образующее дерево в остовном лесу, представленном набором VS. Ребра выбираются из £ в порядке возрастания стоимости. Ребра (v, w) рассматри- ваются по очереди. Если v и w принадлежат одному и тому же множеству из PS, то ребро (г, w) исключается из рассмотрения. Если v и w принадлежат разным множест- вам — W\ и W2 (это значит, что Wt и W2 еще не соединены), то сливаем их в одно множество и добавляем (v, w) к множеству £ ребер, входящих в окончательное ос- товное дерево. Воспользуемся алгоритмом объединения непересекающихся мно- жеств, описанным, например, в разд. 1.1.2 приложения 1 для реализации наборов. Алгоритм 2.3. Краскала Дано. Неориентированный граф G = (К, £) с функцией стоимости ребер с. Требуется. Оптимальный каркас T=(V,S).
Глава 2. Ориентированные деревья 147 Метод. проц ОПТИМАЛЬНЫЙ-КАРКАС (G : граф) = 1. 2. 3. 4 5. 6. 1’ 8. 9 10. S := 0; VS := 0 ; Построить очередь с приоритетами Q, содержащую все ребра из Е; для всех v из Г цикл добавить {v} к VS все; пока |VS| > 1 цикл Выбрать в Q ребро (v, iv) наименьшей стоимости; Удалить (v, iv) из Q; если v и w принадлежат различным множествам ИЛ и ИЛ из VS то заменить ИЛ и ИЛ на ИЛ о ИЛ в VS; Добавить (и, W) к S все все все На шаге 3 алгоритма ребра не сортируются, а хранятся в виде сортирующего дерева, 2-3-дерева (см. разд. 6.1.6) или какой-нибудь другой приемлемой структуры данных, пока они не потребуются. Повторное обращение в строке 6 с целью найти ребро наи- меньшей стоимости является основной операцией с СОРТДЕРЕВОМ [3]. Пример. Для графа G, представленного на рис. 2.65, последовательность действий сведена в табл. 2.5; получившееся в итоге дерево показано на рис. 2.66. Таблица 2.5. Последовательность действий алгоритма Краскала Ребро Действие Множества в VS (связные подграфы) (vl> т?) Добавить {vb v7}, {v2}, {v3}, {v4},{vs}, {v6} (*3, Т4) » {V|, v7}, {v2}, {v3, v4}, {v5}, {v6} (v2, V7) » {vb V2, v7}, {v3, v4}, {v5}, {v6} (Vj. V7) » {Vi, V2, v3, v4, v7}, {v5}, {v6} (ъ, »’з) Отбросить (ч V7) » (v4, V5) Добавить {V|, v2, v3, v4, v5, v7}, {v6} (Vi, v2) Отбросить (Vl, v6) Добавить {vb V2, v3, v4, v5, v6, v7} Алгоритм Прима Этот алгоритм порождает оптимальный каркас посредством разрастания одного под- дерева Д. Разрастание поддерева Д происходит за счет присоединения ребер (v„ vj),
148 Часть I. Обработка и визуализация графов Рис. 2.65. Граф G Рис. 2.66. Результирующее дерево где у е Т, и у, g Ту, причем добавляемое ребро должно иметь наименьший вес cir Процесс продолжается до тех пор, пока число ребер в Т„ не станет равным и - 1. Алгоритм начинает работу с присвоения каждой вершине v, g Ts пометки [а„ Р;], где а, на каждом шаге есть ближайшая к v, вершина из поддерева Т\, а р, вес ребра (а„ Р,). На каждом шаге выполнения алгоритма вершина, например, Vj, с наименьшей по- меткой р, присоединяется к Т„ посредством добавления ребра (а*, г*). Поскольку к Д добавлена новая вершина vj, то, может быть, придется изменить пометки [а,, р,] у некоторых вершин v, £ Ts (если, например, c(v,, v') меньше существующей помет- ки Р ) и после этого продолжить процесс. Алгоритм 2.4. Прима Дано. Неориентированный граф G = (К, Е) с функцией стоимости ребер с. Требуется. Оптимальный каркас T~(V,S). Метод. Ill а г 1. Пусть Д = {у,.}, где у,. — произвольно выбранная вершина, и S, = 0. Ш а г 2. Для каждой вершины v, g Д найти вершину а, е Д такую, что c(aj,Vj,)=min[c(v,, Vj )]=p,, v,e?;s- и приписать вершине у, пометку [a,, p,]. Если такой вершины а нет, т. е. при Гу, п Д = 0, приписать вершине у, метку [0, со]. Шаг 3. Выбрать такую вершину v,’, что P,* = min[P,]- Vj Обновить данные: Д = Д и {у,*}, Sv = S, {(а/, у,*)}. Если |Г | = п, то стоп. Ребра в S, образуют оптимальный каркас. Если |Д| < п, то перейти к шагу 4. Ill а г 4. Для всех v, g Д таких, что v, е Гг', обновить метки следующим образом: П если Р, > c(v‘, у,), то положить р, = c(yj, у,), a, = vj и вернуться к шагу 3; □ если Р, < с(у*, у,), то перейти к шагу 3.
Глава 2. Ориентированные деревья 149 Как видно из описания алгоритма, он может использоваться для нахождения опти- мальных каркасов в графах, близких к полным. Для графа G, представленного на рис. 2.65, последовательные шаги алгоритма Прима приведены на рис. 2.67. v,[v7>1] v2[v7,4] Q ° v3[v7.9] о 'о о vt[v7,36] V7 о о v6[v7,25] v4[v7,16] VNz} V1 *2[*7-4] v6[vir23] v7 v3[v7,9] о о v.[v7>25] vjv7,16] Т^у^уД-изменена метка у v6 о о v5[v7,25] v4[v7,16] Рис. 2.67. Последовательные шаги алгоритма Прима T6=<V1-V2>V7} Алгоритм Соллина Содержательно этот алгоритм состоит из следующих шагов: Шаг 1. Соединить каждую вершину с ее ближайшим соседом. Шаг2. Рассмотреть каждую полученную связную компоненту как одну вершину. Сохранить ребра, ведущие из одной компоненты связности к другой, а затем перейти к шагу 1. Алгоритм Тарьяна — Черитона Содержательно этот алгоритм состоит из следующих трех шагов: Инициализация. Взять некоторую вершину. Выбрать наименьшее по весу ребро, инцидентное этой вершине. Это ребро является первым ребром оптимального кар- каса.
150 Часть I. Обработка и визуализация графов Общий шаг. Ребра, выбранные к этому моменту, определяют лес F, являющийся частичным графом исходного графа. (Изолированные вершины, не инцидентные ни одному ребру, выбранному к данному моменту, рассматриваются как одновершин- ные деревья.) Взять некоторое дерево из леса, пусть это будет Т. Выбрать наимень- шее из ранее не выбранных ребро (v, w), инцидентное вершине в Т и вершине в дру- гом дереве Т'. Удалить все ребра, меньшие (v, w), которые инцидентны Т (эти ребра образуют цикл с ребрами из Т). Добавить (v, и) к оптимальному каркасу (модифици- ровав лес F, объединяя Т и Т'). Повторять общий шаг, пока все вершины не окажутся связанными. Чистка. (Этот необязательный шаг может исполняться после любого исполнения общего шага. Он упрощает последующие вычисления удалением излишних ребер.) Удалить все невыбранные ребра, имеющие оба конца в вершинах одного и того же дерева леса F. Для каждой пары деревьев, связанных невыбранным ребром, удалить все, кроме минимального по весу, ребра, связывающие эту пару деревьев. Данный метод требует наличия механизма для выбора дерева Т и механизма для хра- нения деревьев леса. Объекты Граф G с множеством вершин И={1,2,..., п}, заданный списками смежности I(v). Напомним, что каждое ребро (v, w) встречается в этих списках дваж- ды: в списках /(v) и I(yv). Каждое дерево i леса F определяется множеством i его вер- шин и очередью i ребер, инцидентных ему. Вначале каждая вершина v представляет- ся множеством {v} и очередью, содержащей все ребра из /(v). Операции. Реализация алгоритма предполагает использование следующих опе- раций: НАЙТИ(х)— определяет имя множества, содержащего вершину х; ОБЪЕДИНЕНИЕ^',у) — объединяет множества z иу и присваивает новому множеству имя z; ИНИЦ(д L) — инициализирует множество z, включающее все вершины из списка L; ОЧОБЪЕД(/, j) — объединяет очереди i nj и присваивает новой очереди имя /; МИН(г) — отыскивает наименьшее по весу ребро в очереди z, имеющее один конец вне дерева z, а также удаляет это ребро и все меньшие ребра из очереди z. (Заметим, что MHH(z) должен использовать операцию НАЙТИ для проверки, имеет ли данное ребро концевую вершину вне дерева z); ОЧИНИ Ц(/, £) — инициализирует очередь z, включающую все ребра из списка L. Метод. проц МИНКАРКАС = 1 для / = 1 до л цикл 2. ИНИЦ(/, {/}); 3 ОЧИНИЦр, /(/)); все; 4. пока имеется более чем одно дерево цикл 5. Выполнить чистку (если нужно);
Гпава 2. Ориентированные деревья 151 6. 7. 8. 9 10. 11. все все Выбрать некоторое дерево к; (j j) := МИН(/ф; Добавить ребро (/, j) к оптимальному каркасу; х := НАЙТИ(/); ОБЪЕДИНЕНИЕ^, к); ОЧОБЪЕД(х, к); Особенности реализации. Для реализации строки 10 алгоритма существуют однородный подход и подход "дерево с наименьшим числом вершин вначале". При однородном подходе все деревья организуются в виде произвольной очереди. Берет- ся первый элемент этой очереди— это дерево Т, соединяется с некоторым другим деревом Г, затем оба удаляются из очереди, новое дерево помещается в хвост очере- ди, и процесс повторяется. Трудоемкость такого выбора — О(н). При альтернативном подходе' первым проверяется дерево с наименьшим числом вершин. Этот подход также может быть реализован с трудоемкостью <Э(л), хотя мультипликативная константа в этом случае больше. Он требует хранения числа вершин в дереве и использования массива А размерности и, в котором элемент A(f) есть список деревьев с i вершинами. Так как число вершин в дереве заключается ме- жду 1 и и и никогда не уменьшается, то можно использовать указатель, который движется вдоль массива А для отыскания дерева с наименьшим числом вершин. Мас- сив модифицировать легко, если каждое дерево имеет в нем свой указатель на пози- цию. Существуют также несколько альтернативных подходов к реализации очередей: не- упорядоченный список, список упорядоченных множеств и "левое" дерево. Остано- вимся на первых двух. Представление очереди в виде неупорядоченного списка является простейшим. При этом представлении операция МИН(г) имеет трудоемкость <Э(лг(/)) плюс затраты на использование операций НАЙТИ, операция ОЧОБЪЕД(/,у) имеет трудоемкость 0(1), а операция ИНИЦ(/, £) — трудоемкость (?(/«(/)). Здесь >n(i) — размер очереди I. При представлении в виде списка упорядоченных множеств очередь i есть список множеств, каждое из которых вначале имеет мощность к плюс (возможно) некоторые "специальные" множества мощности меньше к. Каждое множество есть упорядочен- ный список, но само множество этих списков неупорядоченно. Операция ИНИЦ(/, L) исполняется разбиением L на LI b\ /к\ множеств мощности к, где LxJ наибольшее целое число, не превышающее х, и самое большее одно множество мощности меньше к. Затем эти множества упорядочиваются, что требует (?(|Z,| log к) операций. Операция ОЧОБЪЕД(ду) исполняется путем слияния списка множеств в очереди i со списком множеств в очереди j. Это требует 0(1) операций. Операция МИН(0 исполняется проверкой ребер в каждом множестве очереди i по порядку, при этом отбрасываются те из них, которые не соединяют два различных дерева. Потом сравниваются наи- меньшие ребра в каждом таком множестве и выбирается среди них наименьшее. Операция МИН(/) имеет трудоемкость O(s(7) + /(/)) плюс затраты на s(i) + /(i) - 1 one-
152 Часть I. Обработка и визуализация графов раций НАЙТИ. Здесь s(i)— число упорядоченных множеств в очереди i, a Z(Z) — число ребер, удаленных из очереди операцией МИН(/). Предположим, что мы представляем очереди указанным способом, инициализируем в начале р-го шага алгоритма очереди и используем данное представление очереди (т. е. инициализированное в началер-го шага) вплоть до с/-го шага алгоритма. Так как существует не более п/2г очередей в начале р-го шага, то после инициализации име- ют место не более 2mlk + п/2р подмножеств во всех этих очередях. Трудоемкость инициализации очереди — O(m log к). Время исполнения любого шага пропорцио- нально т/к + п!2р + L(j), где L(f) — число ребер, удаленных из очередей. Таким обра- зом, полная трудоемкость инициализации и исполнения алгоритма с шага р по шаг q равна О([т/к + n/2p](q - р) + т). Рассмотрим следующую реализацию алгоритма МИН КАРКАС. Ш а г 1. Инициализировать все очереди как неупорядоченные множества. Ш а г 2. Исполнять МИНКАРКАС до шага log log log п. Шаг 3. Инициализировать заново все очереди как списки упорядоченных множеств мощности к\ = log log п. Ш а г 4. Исполнять МИНКАРКАС до шага log log и. Шаг 5. Инициализировать все очереди как списки упорядоченных множеств мощ- ности к2 = log п. Ш аг 6. Исполнять МИНКАРКАС до завершения. Полная трудоемкость этого процесса равна О(т + т log log log п + т log log и) для инициализации и переинициализации очередей плюс О(т log log log п + т + т) на каждый шаг исполнения (включая все операции ОБЪЕДИНЕНИЯ. НАЙТИ, МИН и ОЧОБЪЕД). Таким образом, полная трудоемкость равна О(т log log п) (для любого способа выбора деревьев) при условии отсутствия чистки вне зависимости от страте- гии выбора деревьев. Более того, время исполнения алгоритма асимптотически до- минируется временем, требуемым для переупорядочения множеств размера 7og п на шаге 5; если это упорядочение использует точные алгоритмы, то эта версия алгорит- ма МИНКАРКАС требует 2т log log п + О(т log log log п + т + т) сравнений. Чистка полезна для графов, в которых МИНКАРКАС порождает много избыточных ребер при комбинировании деревьев. К таковым относятся плоские и плотные графы, т. е. графы, для которых отношение т/п велико. Чтобы выполнить чистку, присвоим номер / каждой вершине в множестве i. Затем заменяем каждое ребро (v, w) ребром, у которого концевые вершины — номера, при- своенные вершинам v и w. (Для каждого нового ребра (v', w') запоминаем соответст- вующее ребро в исходном графе.) Упорядочиваем новые ребра (у', w') лексикографи- чески, используя двухпроходную цифровую сортировку. Удаляются все новые ребра (v', wr) с v' = w' и заменяются экземпляры ребер (v', w') с v'*w' одним, чей вес наи- меньший среди весов всех экземпляров. Этот процесс имеет трудоемкость О(т). За- тем заново инициализируются очереди и множества, представляющие деревья леса F.
Гпава 2. Ориентированные деревья 153 Полезный эффект этих операций состоит в сжатии каждого дерева до одной вершины и в удалении петель и кратных ребер. Предположим, что используется представление очереди в виде неупорядоченного списка. После шага j имеется самое большее н/2'+1 деревьев. Таким образом, имеем д/2/+| новых вершин и (и/2;+1)2 ребер, остающихся после чистки, следующей за шагом j Если w(/) — число ребер в очереди i, когда исполняется МИН(0, то /?—I н %т№%п12^(кп2). 1=1 >0 В данном случае МИНКАРКАС имеет трудоемкость O(min(m log и, и2)). Этот вари- ант алгоритма с однородным выбором деревьев есть версия алгоритма Соллина. Алгоритм отыскания оптимального оркаркаса Заметим, что в отличие от рассмотренной задачи построения оптимального каркаса для неориентированных графов, для которой решение всегда существует, задача по- строения оптимального оркаркаса решение имеет не всегда. Чтобы ликвидировать этот недостаток, обобщим несколько первоначальную постановку задачи. Лесом называется несвязный граф, каждая компонента связности которого является деревом. Ориентированный лес определяется как обычный лес, но состоящий не из простых деревьев, а из ориентированных. При этом предполагается, что все деревья являются заходящими, т. е. имеющими корень, достижимый из каждой вершины де- рева. Оркаркас определен в гл. /; лес-каркасом (покрывающим ориентированным лесом) будем называть частичный граф в виде ориентированного леса (возможно с одно- вершинными компонентами), содержащий все вершины исходного графа. Поэтому, говоря далее о каркасе орграфа, будем иметь в виду оркаркас, если он существует, или лес-каркас — в общем случае. Алгоритм построения максимального в смысле наибольшего по весу лес-каркаса мо- жет быть также использован для решения задач. О Построение минимального по весу лес-каркаса (для этого изменяется знак веса каждой дуги). □ Построение максимального по весу оркаркаса (максимальный по весу оркаркас, если он существует, может не совпадать с максимальным по весу лес-каркдсом); для этого к весу каждой дуги прибавляется достаточно большая положительная константа. □ Построение минимального по весу оркаркаса (если он существует); для этого по- сле изменения знаков всех дуг на обратные к весу каждой дуги добавляют доста- точно большую по величине положительную константу. □ Построение максимального по весу оркаркаса с корнем в заданной вершине (если он существует); для этого к графу добавляется фиктивная вершина г, из которой идет дуга в вершину — заданный корень оркаркаса. П Построение минимального по весу оркаркаса с корнем в заданной вершине.
154 Часть I. Обработка и визуализация графов Алгоритм Эдмондса Алгоритм осуществляет построение максимального лес-каркаса следующим образом. Последовательно в произвольном порядке осуществляется просмотр вершин графа. Цель просмотра состоит в том, чтобы из дуг, заходящих в данную вершину, выбирать дугу с максимальным весом (поэтому вершина, не имеющая заходящих дуг, может быть вообще исключена из рассмотрения). Выбранные дуги помещаются в структуру данных, называемую БУКЕТ. Если добавление новой дуги к уже вошедшим в БУКЕТ не нарушает его свойства образовывать лес, то выбранная дуга вводится в БУКЕТ. В противном случае (когда выбранная дуга образует контур с некоторыми дугами, ранее вошедшими в БУКЕТ) формируется новый уменьшенный граф путем стягива- ния дуг и вершин выявленного контура в одну вершину. В новом графе веса некото- рых дуг соответствующим образом корректируются. Кроме того, для нового графа корректируется состав БУКЕТа вершин и БУКЕТа дуг- в них остаются только те эле- менты (вершины или дуги), которые присутствуют в новом графе. После проведен- ной корректировки процедура просмотра вершин продолжается аналогичным обра- зом и заканчивается, когда просмотрены все вершины исходного графа. По окончании процедуры просмотра вершин дуги последнего сформированного БУ- КЕТа образуют лес-каркас в соответствующем графе. После этого осуществляется переход ко второму этапу алгоритма, состоящему в следующем Граф, полученный по окончании первого этапа, расширяется путем замены фиктивной вершины конту- ром, который в нее стягивается при соответствующем преобразовании графов. В но- вый расширенный граф, а также в соответствующий ему БУКЕТ включаются все ду- ги указанного контура, за исключением одной. Исключенная дуга выбирается так, чтобы дуги, составляющие новый БУКЕТ, образовывали лес в соответствующем графе. Этот процесс последовательного расширения графа продолжается до тех пор, пока не будет восстановлен исходный граф. При этом оказывается, что дуги соответ- ствующего БУКЕТа образуют для исходного графа максимальный ориентированный лес. Алгоритм 2.5. Эдмондса Дано. Граф G = (К, £), заданный обратными списками смежности. Требуется. Множество 5 дуг максимального лес-каркаса. Метод. проц ЛЕС-КАРКАС (G : граф) 1. БУКЕТВ = 0; 2. БУКЕТД := 0; 3. /:=0; 4. пока |БУКЕТВ| * |V) цикл 5. Выбрать вершину v из V \ БУКЕТВ; 6. БУКЕТВ := БУКЕТВ u {v}; 7. Выбрать дугу и с максимальным весом, заходящую в v; 8. БУКЕТД := БУКЕТД u{u}; 9. если и не замыкает контур С, то на 5; все 10. Выявить контур Ст,
Гпава 2. Ориентированные деревья 155 % определить множества V, = {v„.Vj } вершин и Еду г С,-% 11. БУКЕТВ = БУКЕТВ W,u{vl}; % эта операция соответствует стягиванию контура С, в новую вершину Vi % 12. БУКЕТД := БУКЕТД \ Е; 13. для всех (х, у) е БУКЕТД цикл 14. если у е V/ то заменить дугу (х, у) дугой (х, у,) с весом с(х, и,) = с(х, у) + c(r, s) - с(/, у), где (г, s) — дуга, имеющая в контуре С, минимальный вес, (f, у) — дуга С/, заходящая в вершину у все; 15. если х e I/, то заменить дугу (х,у) дугой (и,,у) все; все; 16 /:=/+1; все; 17. для i = |V| до 1 цикл 18 если V/-1 является корнем некоторого ордерева в лесе, образуемом дугами из БУКЕТД 19. то удалить из контура См дугу с наименьшим весом; 20. БУКЕТД := БУКЕТД и {оставшиеся дуги контура См}; 21. иначе % в этом случае в БУКЕТД имеется единственная дуга (х, Ум). заходящая в вершину vm; эта дуга соответствует некоторой (х,у) дуге, где у — вершина контура См, стянутого в вершину Ум % 22. БУКЕТД := БУКЕТД и (Ем \{(f, у)}; % см.строку 14 % все все; 23. S := БУКЕТД; все Рассмотрим пример использования алгоритма для построения максимального лес- каркаса для графа G, представленного на рис. 2.68. Рис. 2.68. Исхордный орграф G
156 Часть I. Обработка и визуализация графов Вершины графа просматриваются в их лексикографическом порядке, дуги, включен- ные в БУКЕТД (рис. 2.69), выделены жирными линиями, веса дуг указаны возле со- ответствующих дуг. Веса дуг остаются С О Рис. 2.69. Работа алгоритма Эдмондса Алгоритм Тарьяна проверки каркаса на оптимальность Пусть G = (H, Е)— граф и Т— каркас графа G. Возникает вопрос: является ли Т оптимальным каркасом для G? Найти ответ на него помогает следующий критерий: А. Каркас Т оптимален тогда и только тогда, когда для каждого ребра (и, w) у Т выполняется условие с(и, и>) > max {с(х, у) | (х, у) лежит на пути и —у w Т Для реализации проверки оптимальности каркаса предлагается следующий алгоритм. Вычислим максимальный вес ребра из ребер пути по каркасу, соединяющему верши-
Глава 2. Ориентированные деревья 157 ны каждого ребра, не входящего в дерево, и применим критерий 2.4 1, А Приводи- мая ниже реализация этого подхода в виде процедуры ОЦЕНКА-ПУТЕЙ имеет тру- доемкость О(т аЦт, л)), если G имеет т ребер и п вершин. В ней используются сле- дующие операции, реализация которых приведена ниже: ОЦЕНКАМ)— найти корень дерева, содержащего в текущий момент вершину v, скажем г, и максимум меток вершин на пути из v в г; СВЯЗЬ(г, w)— слить деревья с корнями v и w в отдельное дерево с помощью добав- ления ребра (v, w) так, что новым корнем становится вершина v (это делает v отцом вершины w); ОБНОВЛЕНИЕ^, х) — заменить I на тах(х, /), если и —• корень дерева и и имеет мет- ку Г, НОП(и, w) — для вершин v и w найти их общего предка в дереве; СЖАТИЕ-ПУTH(v) — см. приложение 1, разд. 1.1.4. Идея алгоритма состоит в следующем. Пусть Т — каркас, выберем произвольно ко- рень каркаса, пусть это будет вершина г. Для каждой пары (v„ w,), определяющей ребро, не входящее в каркас, найдем вершину и, = HOH(v„ w,) и вычислим максимум весов ребер, лежащих на пути из и, в v, и на пути из и, в w(. Сравнивая эти две оценки, дадим ответ для каждой пары (v„ w,). СЫН(и) есть множество сыновей вершины v в Г, ОТЕЦ(г) — предок v в Т. проц ПОИСК (и : вершина) = 1. для каждого сына v вершины ив Т цикл 2. ПОИСК(у) все; 3. для всех (у, и/) из БУКЕТ(о) цикл 4. OTBET(v, w) := если и = и то ОЦЕНКА(их) иначе если и = vto ОЦЕНКА(у) иначе тах(ОЦЕНКА(у), ОЦЕНКА(и/)) все все все, 5. для всех v из СЫН(и) цикл СВЯЗЬ(г/, v) все все; проц ОЦЕНКА-ПУТЕЙ (г: вершина) = 1. для всех v из V - {г} цикл 2. I(v) := (ОТЕЦ(у), v); 3. БУКЕТ(и) := 0 все; 4 для каждого ребра (и, w), не принадлежащего каркасу Т цикл Добавить (у, w) в БУКЕТ(НОП(у, w)) все; ПОИСК(г) все Очевидно, что трудоемкость алгоритма определяется эффективностью реализации указанных операций.
158 Часть I. Обработка и визуализация графов Операция НОП(у, w). Данная операция реализуется следующим алгоритмом: проц ПОИСК1 (и: вершина; п : набор) = 1. для всех w из СЫН(у) цикл 2. ПОИСК1 (iv); слить wc vb п все; 3. для каждого ребра (v, iv), не принадлежащего каркасу Т цикл 4. если (V, iv) помечено то 5. снять пометку с (v, w) 6. иначе НОП(к, iv) := найти iv в п все все все; проц НОП = 1. л: набор = {({v}, v): v е V}; 2. Пометить все ребра (v. iv), не принадлежащие каркасу Т, 3. ПОИСК(г) все Как можно видеть, процедура ПОИСК1 реализует поиск в глубину. Во время ее вы- полнения каждое ребро (v, w), не принадлежащее каркасу, просматривается дважды: один раз при посещении v, второй — w. Во время второго обхода ребра (v, м>) вычис- ляется HOFI(v, w) и хранится в HOfI(v, w). Трудоемкость операции НОП — О((т + и) a(w + п, и)). Операция ОЦЕНКА(г). Данная операция реализуется следующим алгоритмом: проц СЖАТИЕ (и: вершина) = 1 если ОТЕЦ(ОТЕЩу)) * 0 то 2. СЖАТИЕ(ОТЕЦ(у)); 3. /(v) := тах(/(ОТЕЦ(и)), /(v)); 4. ОТЕЦ(у) := ОТЕЦ(ОТЕЦ(|/)) все все; функ ОЦЕНКАМ. вершина): вещ = 1. если ОТЕЦ(и) = 0 то 2 ОЦЕНКА := /(V) 3. иначе СЖАТИЕ(у); 4. ОЦЕНКА := тах(/(ОТЕЦ(у), /(V)) все все Операция СВЯЗЬ(у, w). Пусть каркас Тимеет структуру, показанную на рис. 2.70. Для любого корня г7 поддерева STj СЫН (г;) = г7+|, если j <k,u СЫН(г;) = 0, если j = к. Для любого корня г} обозначим через РАЗМЕР(г7) число потомков г7 в VT(VT— дере- во, получающееся из Т после проведения операций СЖАТИЕ и СВЯЗЬ), т. е. /с РАЗМЕР(г7)= '=>
Глава 2. Ориентированные деревья 159 Рис. 2.70. Каркас Т где l-S’7’,1 есть число вершин в ST (для удобства мы будем употреблять для |57’,| также выражение СУБРАЗМЕР(г,)). Положим для определенности РАЗМЕР(О) = 0, тогда СУБРАЗМЕР(г,) = РАЗМЕР^) — РАЗМЕР(СЫН(г,)). проц СВЯЗЬ(|/, iv) = 1. ОБНОВЛЕНИЕ^, /(v)); 2. PA3MEP(v) := PA3MEP(v) + PA3MEP(tv); 3. s = w 4. если РАЗМЕРА) > 2 PA3MEP(w) то (s, CblH(iz)) := (CblH(iz), s) все; 5. пока s * 0 цикл 6. OTEL|(s) := v; 7. s := CblH(s); все все проц ОБНОВЛЕНИЕ^, х) = 1. % эта процедура предполагает, что РАЗМЕР(О) = 0 и /(0) = °о % 2. /(г) := max(x,/(r)); 3. L1: пока /(г) > /(СЫН(г)) цикл 4. п := СЫН(г), 5. 12: пока /(г) > /(CblHpi)) цикл 6. если РАЗМЕРА + РАЗМЕР(СЫН(СЫН(п))) > ^гРАЗМЕРССЫНСл)) 7. то ОТЕЦ(СЫН(/1)) := и; 8. CblH(ri) := СЫНССЫН^)) 9. иначе РАЗМЕР(СЫН(Г|)) := РАЗМЕР(л) 10. г, := OTELtfr,) := СЫН(л); все все;
160 Часть I. Обработка и визуализация графов 11. /(и):=/(г); 12. СЫН(И:=Г1 все все Заметим, что выбор 1(0) = °о гарантирует, что L\ не исполняется, если СЫН(г) = 0, и L2 не выполняется, когда CbIH(rj) = 0. Заметим также, что 5- исполняется в точности тогда, когда РАЗМЕР(г)) + РАЗМЕР(СЫН(СЫН(г,))) > 2-РАЗМЕР(СЫН(г))), т. е. когда СУБРАЗМЕР(г[) = РАЗМЕРА)) - РАЗМЕР(СЫН(г))) > > РАЗМЕР(СЫН(Г|)) - РАЗМЕР(СЫН(СЫН(Г]))) = СУБРАЗМЕР(СЫН(г,)). 2.4.2. Алгоритмы перечисления всех каркасов Алгоритм Винтера Пусть G — связный неориентированный граф с и вершинами и п ребрами. Пусть да- лее Т„— некоторый каркас графа G. Граф называется собственно размеченным, если его вершины занумерованы по следующему правилу. Выберем какой-либо лист кар- каса Т„ и присвоим ему номер п, удалим этот лист и ребро, инцидентное ему В полученном дереве T„-i снова выберем какой-нибудь лист и присвоим ему номер и - 1, удалим лист и - 1 и т. д. Пусть теперь п,— вершина, смежная с вершиной п в собственно размеченном гра- фе G. Пусть граф G"' получается из G с помощью следующих операций. 1. Все ребра, соединяющие вершины и - 1, и - 2,..., nt с п, удаляются из G. 2. Оставшиеся инцидентные и ребра делаются инцидентными вершине л,. 3. Вершина л удаляется из G. Будем говорить в этом случае, что Gn' получается из G собственным втягиванием и в Л/. Ясно, что G"' есть собственно размеченный мультиграф с л - 1 вершиной с но- мерами 1,2,... л - 1 (параллельные ребра возникают как результат втягивания). Основная идея алгоритма состоит в следующем. Пусть Р — множество всех каркасов собственно размеченного мультиграфа Gen вершинами. Обозначим через Ди) = {иь л2,..., и,} множество вершин, смежных с и, и через Р”‘, k = 1,2,.., t, мно- жество каркасов, у которых имеется ребро (и, л*) (точнее, одно из параллельных ре- бер, соединяющих л и и*) и нет ребер, соединяющих и с л*+1, пк,2,..., и„ т. е. Р”‘ = {Г е Р | (л, и*) е Т, (и, и4+|) g Т,..., (и, и,) g Т } Ясно, что {Рп',РПг, ..., Р"'} есть разбиение Р, и чтобы перечислить все каркасы из Р, нужно вначале перечислить все каркасы из Р,1{, затем из Р"2 и т. д. Пусть G"‘, к = 1,..., г, есть мультиграф, полученный из G собственным втягиванием и в пк. Каж-
Гпава 2. Ориентированные деревья 161 дому каркасу в Gn" соответствует единственный каркас графа G из Р\ Верно и об- ратное, каждому каркасу графа G из £"* соответствует единственный каркас графа G"k. Следовательно, каждое множество £"*, к= 1, 2,..., Z, может быть дальше разби- то, используя ребра, инцидентные вершине и - 1 в G”‘, тем же способом, каким Р было разбито, используя ребра, инцидентные и в G. Действуя таким образом, множество Р можно разбить на взаимно различные, непус- тые подмножества Ра', Ра*, Р“2, ..., £“', где а„ г = 1,2,... s, есть последователь- ность из n - I (не обязательно различных) вершин г„, г„_ь ..., г2 и г„ обозначает вер- шину в G, в которую была втянута вершина и для получения Gr" ,гп_} обозначает вершину Gr", в которую была втянута вершина и - 1 для получения (G,"),"‘ = Gr"r"~' и т. д. Заметим, что i > г, для каждого i = n, п - 1,..., 2 и G°r состоит всего из одной вершины 1. Пусть G— собственно размеченный граф с ребрами, занумерованными числами 1, 2,..., tn. Введем следующие обозначения: □ G$r — мультиграф, получаемый из G с помощью IPJ = к, 0 < к < и - 1, последова- тельных собственных втягиваний, т. е р,- есть последовательность вершин г„, г„_ь ..., r„-*+i, описанная выше; GPr есть собственно помеченный мультиграф с и - к вершинами с номерами 1, 2,..., и - к; П E(j, /)— множество ребер из G, соединяющих j и i в GPr, j = 2,3,..., и-к, i= 1,2, ...,J - 1; предполагается, что E(j, i) организовано в виде простого списка; □ F(J, i) — первое ребро в E(j,iy, П £(/', г) — последнее ребро в E(j,iy, □ ££(/) — (/ = 2, 3,..., п - к) множество всех £(/, /),«= 2, 3,..., и - 1, которые не пус- ты; предполагается, что EE(j) организовано в виде двусвязанного списка. Кроме того, определим: □ FF(j) = i, где £(/, /) — первое множество из EE(j)’, □ LL(J) = I, где £(/, 0 — последнее множество из EE(j)\ □ MM(j) = max {i | £(/, г) е ££(/)}. Мультиграфы GPr ‘ генерируются для каждого r„_*, 1 < г„_* < и - к, при условии, что £(и - к, г„_к) е ЕЕ(и - к), в порядке убывания их меток г„_к. Для получения ‘ необходимо выполнить следующие шаги. Шаг 1. Переупорядочить ЕЕ(п-к) так, чтобы все множества, следующие за £(//- к, г„_к), были уже обработаны. Так как ЕЕ(п - А) есть дважды связанный список, это может быть сделано за время G(l) при условии, что указатель R(n — к) на множе- ство £(и - к), в ЕЕ(п - к), обработанное ранее, доступен. Если г,,_* = ММ(п - к) (т. е. если ни одно множество из ЕЕ(п — к) еще не обработано), то £(и - к, г,,-^ пере- двигается в самый хвост ЕЕ(п - к). 6 Зак. 202
162 Часть I. Обработка и визуализация графов Шаг 2. Представление G*3' получается путем добавления Е(п — k, i) г- ЕЕ{п - к) к Е(гп-к, О Для каждого Е(п - к, I), встретившегося при просмотре ЕЕ(п - к), пока не достигнуто Е(п - к, гп-к). Для каждого встретившегося Е(п - к, i) могут иметь место следующие возможности: 1. Е(г„_*, I) * 0. В этом случае Е(п — к, i) добавляется в хвост /). Для того что- бы иметь возможность восстановить G^, когда был обработан G*3' г"-1 исходный указатель на последний элемент в E{rn-k, i) передвигается в стек. Для данного и-к, 0<к<п- 1, стек содержит самое большее и-к-2 элемента. Таким обра- зом, размер стека ограничен сверху величиной п-2 У^(п-к-2) = (п-2)(п-1)/2. к=о Заметим, что в течение обработки GPr множество Е(п - к, г„_к) остается неиз- менным. 2. Е(гп_к, 0 = ±. В этом случае создается E(r„_k, I) = Е(п — к, I). Заметим, что нет необ- ходимости помещать исходный указатель на последний элемент в E(r„_k, i) = 0 на стек, т. к. пустое множество может быть восстановлено проверкой, выполняется ли равенство F(n - к, I) = F(r„-k,i). Создание Е(ги_*, /) требует, чтобы оно было добавлено к ЕЕ(г„_к). Может случиться, что < i. Если это так, то пусть MM{rn-k) = 1, в то время как исходное значе- ние помещается в стек. Так как случаи 1 и 2 не встречаются одновременно, может быть использован один и тот же стек. Ясно, что и 1 и 2 могут быть выполнены за время 62(1). Шаг 3. Для данного представления G₽r'"* алгоритм осуществляет (рекурсивную) обработку G^r * . По завершении ее представление G₽r должно быть восстановле- но. Это может быть сделано просмотром элементов, предшествующих Е(п - к, r„-k), в ЕЕ(п - к), в обратном порядке. Для каждого встретившегося Е(п — к, /) может иметь место один из следующих случаев: (a) F(n -к,1)Ф F(r„-k, /). В этом случае исходное E(r„_k, I) не пусто и указатель на последний элемент находится в вершине стека. (б) Е(п - к, i) = F(r„-k, /). В этом случае исходное £(/„_*, 0 пусто. Текущее Е(ип_к, I) удаляется из ЕЕ(г„^). Более того, если ММ(гп~к) = /, то исходное значение ММ(г^ находится в вершине стека. Таким образом, (а) и (б) могут быть выполнены за время 0(1). Ш а г 4. Когда восстанавливается G*3' из GPr ‘ определяется наибольшее i (обо- значаемое г"_к), встретившееся при просмотре ЕЕ(п - к). Это г"_* (если оно сущест- вует) замещает г„_*, и G^'r”‘ порождается тем же способом, каким было порождено G₽r Если не существует, возвращаемся на шаг назад.
Глава 2. Ориентированные деревья 163 Из приведенных выше рассуждений следует, что время, необходимое для получения представления сА из G$r, так же, как и время для восстановления G*5,, равно 0(c), где с есть число просмотренных элементов ЕЕ(п - к). Алгоритм Винтера Для облегчения понимания в описании алгоритма опущены детали получения G₽r из G₽r и восстановления GP' из G₽r . Смысл процедур МЕТКА, ИНИЦИАЛИЗАЦИЯ и ВЫХОД будет пояснен после описания основной части алго- ритма. проц ВТЯГИВАНИЕ (G : граф; к: цел) = 1 (Гл-*, г'п-*) := (ММ(п -к),п- к); 2. пока г„-к * 0 цикл 3. если п - к = 2 то 4 ВЫХОД 5. иначе передвинуть Е(п - к, гп-к) так, чтобы оно предшествовало Е(п - к г'п-к) в ЕЕ(п - к), 6. для каждого Е(п - к,Г) такого, что 7 < Гп-к цикл 7 £(гл-*,/) <= Е(п - к, 7); 8. ВТЯГИВАНИЕ^, к+ 1); 9 R"„_k := 0; 10. для всех Е(п - к, i) таких, что 7 < Гп-к цикл;' 11 Удалить из Е(гп~к, i) все ребра, принадлежащие Е(п - к, i); 12. если 7 > г"п-к то г"п-к 7 все, 13 (Г*п-к, Тп-к) — (Гп-к, Г п-к) все все все все все; проц ПЕРЕЧИСЛЕНИЕ (G граф) = 1. METKA(G); 2. ИНИЦИАЛИЗАЦИЯ(С); 3 ВТЯГИВАНИЕ^, 0) все Процедура МЕТКА обеспечивает собственную разметку графа G. Более того, для уменьшения числа рекурсий рекомендуется руководствоваться следующим интуи- тивным правилом: вершины следует помечать так, чтобы вершины с большей сте- пенью имели бы меньшие номера. Может быть использован следующий подход: начало 1. Выбрать вершину с наибольшей степенью и присвоить ей номер 1; 2 для 7 от 2 до л цикл
164 Часть I. Обработка и визуализация графов 3. среди всех вершин, смежных хотя бы с одной помеченной вершиной, выбрать вершину с наибольшей степенью в G и присвоить ей номер i все конец Эта процедура может быть реализована так, что ее трудоемкость будет равна О(п + т) с требуемой памятью О(п + т). Процедура ИНИЦИАЛИЗАЦИЯ порождает списки E(j, /) и EE(j) для собственно по- меченного графа G. E(j, i) пусто, если вершины j и i не смежны, в противном случае £(/, I) содержит единственное ребро (/, i). Если G задан списками смежности, то тру- доемкость этой процедуры равна О(т). Процедура ВЫХОД составляет список элементов декартова произведения Е(п, г„) * Е(п - 1, r„-i) х ,..х£(2,1). Каждое множество из таких п - 1 ребер есть каркас графа G. Общая трудоемкость алгоритма равна О(п + т + nt), где t— число всех каркасов дан- ного графа. Алгоритм Чена генерирования оркаркасов Данный алгоритм основан на алгебре Вана, определенной на множестве частичных графов данного графа. Дадим краткое введение в эту алгебру. Пусть G — связный неориентированный граф с вершинами К= {го, vi, ..., гД и ребра- ми {/], /2,..., 1Р} и пусть А = {G(,..., ОД, S = 2₽, есть множество его частичных графов. Частичный граф без ребер (пустой граф) будет обозначаться единицей. Пусть S = {Si, S2, ..., 5Д, k = 2s есть множество всех подмножеств множества А. Оно включает пус- тое подмножество, обозначаемое 0. Определим коммутативное кольцо над S, яв- ляющееся алгеброй множеств частичных графов данного графа. Кольцевой суммой (симметрической разностью) S, ® S, для всех S„ S, е S называется множество всех частичных графов, которые содержатся либо в S„ либо в Sj, но не в обоих вместе. Сложение обладает следующими свойствами: □ коммутативности: S, ® S7> = SyО S,; □ ассоциативности: ® (Sj ® Sk) = (S, ® S7) Ф S); □ замкнутости: S, Ф S, е S; □ существования нуля: 0 ® S, = S,; □ существования отрицательного элемента: S, © S, = 0. Произведением Вана S, Sj, S„ Sj е S называется кольцевая сумма всех частичных графов, каждый из которых есть объединение двух не пересекающихся по ребрам частичных графов, одного из S, и другого из Sr Умножение обладает следующими свойствами: □ коммутативности: Sj-Sj = Sj- S,', □ ассоциативности: S, (S} • S*) = (S, • S7) Sk;
Гпава 2. Ориентированные деревья 165 □ замкнутости: S, Sy е S; □ существования единицы: 1 S, = S,; □ наличия поглощения (I): X, S, = 0 при условии, что 5, не содержит множества 1; □ существования единицы (II): S, S, = 1 при условии, что S, содержит множество 1; □ наличия поглощения (П): 0 S, = 0. В приложении к графам это означает, что все частичные графы, содержащиеся в лю- бом фиксированном множестве S,, имеют одно и то же число ребер. Таким образом, множество X, может содержать 1 только в случае, когда S, = 1. Имеет место следующее соотношение: A. S, (Sj Ф Sk) = Sf -Sj Ф < S, • Sk для любых i,j и к. Имеют место следующие утверждения: Б. Любой частичный граф может быть записан как произведение его ребер, т. е. О, = Пч ej^G, В. Любое множество частичных графов может быть записано как кольцевая сумма его элементов'. s,= { G,...., Gk) = {G, }®{G, }©...© {GJ = ©{( f[ej. 7 ' еч6°’| Фундаментальные теоремы алгебры Вана связывают между собой различные множе- ства частичных графов, что позволяет генерировать разные виды частичных графов из более простых. При обобщении алгебры Вана на случай ориентированных графов дуги (v„ v;) и (v,, v,) при всех операциях рассматриваются как один элемент или, более общо, операция умножения переопределяется так, чтобы можно было избежать появления запрещен- ных конфигураций дуг. Перейдем теперь к изложению алгоритма Чена генерирования всех оркаркасов. Пусть G = (И, £)— симметричный орграф и пусть X, — множество дуг, исходящих из вершины V,. Для удобства дуги (ve, vk) и (vk, vc) будем обозначать е, и е'. Справедливо следующее свойство (теорема Чена): Теорема Чена. Пусть для данного симметричного графа G X есть произведение Вана (в котором дуги е, и е\ рассматриваются как идентичные) множеств Sh i Ф г, /=1 Mr Тогда множество Tr— {Л]} © {Xi } © ... © {А?и}, Х[е Хг, т= |ХГ|, есть множество оркаркасов с корнем в vr.
166 Часть I. Обработка и визуализация графов Как следствие, получаем, что для генерации множества каркасов с корнем в заданной вершине для произвольного орграфа достаточно дополнить его дугами до симмет- ричного графа, а затем удалить из Тг элементы, содержащие добавленные дуги. Рассмотрим работу алгоритма Чена. Для графа G (рис. 2.71) соответствующий сим- метричный граф показан на рис. 2.72; дополнительные дуги помечены буквами с двумя штрихами. Множество S|-S2-S3 для графа G равно: Si-SrS3={e3, es, е4}-{е2, е3}-{е2, et'j^ejeJe", е5е2е4', ese3e2, е5е3е", е4е3е2}, а соответствующее множество каркасов с корнем в вершине v4 есть = {е3 е2 е4 } ® { е3 е2 е4 } ® {е5 е2 е4 } ® {е5 е3 е2 } ® {е5 е3 е4 }={е5 е3 е2 }. Рис. 2.71. Граф G Рис. 2.72. Симметричный граф, соответствующий графу G Генерирование каркасов во взвешенном графе В случае взвешенного графа задача генерирования каркасов ставится как задача ге- нерирования каркасов в порядке увеличения их весов, начиная с оптимального кар- каса. j-м минимальным каркасом 7} будем называть каркас, удовлетворяющий сле- дующему рекурсивному определению: □ Т] — каркас с наименьшим весом; □ Tj(j> 2) есть каркас с наименьшим весом, отличный от каркасов 7), Т2, , Т2-\. Весом элементарного преобразования каркасов (см. гл. 1) [и, v] (т. е. перехода от кар- каса Т к каркасу Т' = T-iojv) называется величина w[u, v] = w(v) — w(u), таким обра- зом, w(T-и u v) = w(T) + w[u, v]. Имеет место следующее утверждение: Г. Каркас имеет наименьший вес, когда для него не существует элементарных пре- образований с отрицательным весом. В основе описываемого алгоритма лежит следующее свойство. Д. Пусть Т — каркас с наименьшим весом графа G = (V,E) и пусть IN cz Т и OUT с а Е - Т, где IN и OUT — данные подмножества Е. Тогда каркас с наименьшим ее-
Гпава 2. Ориентированные деревья 167 V сом, отличный от Т и удовлетворяющий тем же самым ограничениям, получается как Т— u'Jv, где [и, v] — элементарное преобразование с минимальным весом, удов- летворяющее условиям и е. T—lNuveE—T— OUT. Пусть 7\— оптимальный каркас. Множества IN, и OUT; определяются следующим образом: П IN, = 0, OUT, = 0; □ если Т'=Т, - uuv, то OUT, = OUT, о {v*} и IN,* = IN, u {v*}, OUT,’ = OUT,*. Определим также следующие вспомогательные множества. Предположим, что пер- вые j - 1 (/ >1) минимальных каркасов уже построены, тогда оставшиеся разбивают- ся на) - 1 непересекающихся множеств РГ' = {тк I к >J - 1, IN, с Тк, OUT, с Е - Тк}, где/ = 1,2,1. Кроме того, для i = 1,2,..., j- 1 положим 2/ * = {([w, VL r) I Д™ каждого v е Е - 7,-OUT,, и е Г,-IN, определяет минималь- ное элементарное преобразование [w, v] с весом г — w[u, v]}. Заметим, что всякое множество Q' 1 содержит \Е-Т,- ОиТ,|=О(«г) меток. Каждое множество Р-*~х представляется набором Р/-' = (С, [и', v], А„ IN,, OUT,,/), где ([д', v*], г') есть метка из Q/"1 с наименьшим г и /'= w(T,) + r'= w(T—и'и v*). А, есть список смежности для Т(, т. е. А, = {Л,(х)|х е 7} и А,(х) = {у| ребро (х, у) е 7,}. Длина Р/-1 равна О(т), т. к. |Л,| = О{п) и [INJ + |OUT,| = О(т). При реализации алго- ритма с Я,(х) сопоставляется больше информации, считая, что Л,(х) состоит из сле- дующих наборов: А,(х~) = {(У, MX, У))> INFLAG|(x, у) Т,}, где INFLAG = 0 означает, что (х, у) IN,, a INFLAG =1 — что (х, у) е IN,. Мы также используем списки смежности графа G: Ag = {Ag(x) I х е V}, Ag{x) = {(у, w(x,y)) | (x,y) e £}, а также функции вычисления: ВЫЧИСЛЕНИЕ-01, ВЫЧИСЛЕНИЕ-02, ВЫЧИСЛЕ- НИЕ-^, описание которых приведено ниже.
168 Часть I. Обработка и визуализация графов проц ГЕНЕРАЦИЯ (Р{ 1... Р]_] , О/ 1. . .. QJj_] : множество) = 1. Найти Р./-1 = (f*,[e*, Г], A?, IN;- , OUT]-. П с наименьшим весом Г среди элементов {Ру-1 =(t', [е‘, f], Ah IN,, OUT,, /); i e [1 :/)}; 2. если Г = co то 3. Все каркасы построены и G содержит только j -1 каркасов 4. иначе А, «- А* с ребром е* замененным на ребро /, где А;— список смежности каркаса Т/ 5. Q/<-Q/--1-{([е’, И], Г -1/)}; 6. Оу <- ВЫЧИСЛЕНИЕ-ОЗ(А, IN.- и iX, OUT- И, О<“1); 7. для всех i из [1 : j) - {Г} цикл в/ «- Q^-1 все; 8. если QZ * 0 то i 9. Р/ <-(t+<[6', 1/1, A,., IN(- , ОШ/ и и’, Г), где ([д',1/1, г*) есть метка в Q/. с минимальными г, и вес tj каркаса Г. может быть вычислен по формуле Г - w[e’, и’] 10. иначе Pl <- (со, 0, 0, 0, 0, Г) все; 11. если оу * 0 то р/ <- (Г +г", [е", и"], Aj, INf и/, OUT,., j), где ([е", i/'l г") — метка в Q1 с наименьшим г 12. иначе Pj <- (со, 0, 0, 0, 0, Г) все; 13. для всех / из [1J) - {Г} цикл Pj <- Р/-1 все все все; проц КАРКАСЫ (G : граф; к: цел) = 1. %к>2% 2. Найти список смежности At для оптимального каркаса Tt и его вес tt', 3. если л2 < ma(m, л) то 4. ОУ <- ВЫЧИСЛЕНИЕ-01 5. иначе в} <- ВЫЧИСЛЕНИЕ-02 все; 6. Найти минимальное элементарное преобразование ([л', и], г1) в ; 7. РУ <- (fi + ri [е', и], At, 0, 0,1);
Гпава 2 Ориентированные деревья 169 8 для j от 2 до к цикл 9. ГЕНЕРАЦИЯ( “V .QjZi) все все Функция ВЫЧИСЛЕНИЕ-^! вычисляет 21* за О(п2) шагов путем нахождения [и, v] и r=wfu, v] как наименьшего по весу элементарного преобразования для каждого дан- ного ребра v = (x,y) е Е— Т\. Она представляет собой несколько расширенный алго- ритм Прима. Рассмотрим тот шаг алгоритма Прима, когда к текущему фрагменту оптимального каркаса добавляется ребро (х, z), где вершина х принадлежит фрагмен- ту, а вершина z нет. Для каждой вершины у из фрагмента обозначим через (А, А) реб- * ро с наибольшим весом на пути у—>к из у в х по каркасу Tt. Тогда ребро максималь- ного веса па пути y-»z для v = (x, z) получается путем выбора ребра с наибольшим весом из (х, х) и (А, А). Эти вычисления ребер с наибольшим весом для всех (х,у) та- ких, чтох суть вершины из фрагмента выполняется за время О(и). Так как это может быть повторено и - 1 раз, пока будет построен каркас Т\ по методу Прима, одновре- менно с вычислением ребра с наибольшим весом для каждого v = (х,у) е £, полное время вычисления Q' равно <9(п2). Функция ВЫЧИСЛЕНИЕ-^ представляет собой адаптацию алгоритма Тарьяна (см. разд. 2.4.1) с трудоемкостью O(ma(m, и)) проверки того, что данный каркас Т неори- ентированного графа есть оптимальный каркас. Этот алгоритм включает вычисления ребра с наибольшим весом на пути у-* у для каждого ребра w = (x, у) е Т. Поэтому эта часть его алгоритма может быть использована непосредственно как функция ВЫЧИСЛЕНИЕ-^ для вычисления Q1. Функция ВЫЧИСЛЕНИЕ-23 служит для получения 2/ за ()(т) шагов, когда задано дерево Т, = Т* - u v‘, где [и , v*] есть наименьшее элементарное преобразование в |J2/ ' ВЫЧИСЛЕНИЕ-23 основывается на следующем свойстве, и Е. Для Tt и ребра v* = (х*, у’), определенных выше, пусть Т^х") и Tfy?) — два де- рева, полученные из 7} удалением v*, где х* е И,(х*) и у*е ЕДу*). Здесь 1',(х) есть мно- жество вершин в связной компоненте 7}(х). Пусть также v = (х, у) есть ребро из Е — Tj-OUT,. Тогда: □ если х, у е Е,(х*) или х, у е У/у*), то метка ([w,v],r), хранящаяся в QJ,~X, содер- жится также и в Q J. ; □ если х 6 Е,(х”) и у е Ej(y*), то ([u, v], г), хранящаяся в Q ' , определяется по фор- мулам:
170 Часть I. Обработка и визуализация графов W(u) = max[max { W(g) | g £ fNp g лежит на пути x* Т^х*) max { W(h) | h £ IN,, h лежит на пути у* г = lV(v) — lV(u). Для эффективного вычисления ([и, v], r)e Qj в соответствии с приведенным свойст- вом функция ВЫЧИСЛЕНИЕ-^3 предварительно обрабатывает деревья 7}(х) и 7j(y‘) путем вызова подпрограмм EDGEFIND(^7, х‘, IN,) и EDGEFIND(/f,r, у*, INj), где А/ есть список смежности для Т}(х") о 7}(у’). Вызов EDGEFINDG4/, х‘, IN,) находит ребро наибольшего веса MAXEDGE’ (х) е 7,(х') - IN, на пути х* -> х для каждой верши- 7,(х*) ны х е 7j(x*). Его вес хранится в W*(x). (Индекс х* добавляется для обозначения MAXEDGE и W, полученных с помощью EDGEFIND(A/, х*, IN,)). Вызов EDGEFIND(?4/,y’, IN,) действует аналогично После этого (|MAXEDGE|/(z), v], IF(v) - WV(z)) добавляется к Qj для каждого ребра v = (х, у) е Е - Tj - OUT; сх е Е/х’) ну е ^(у*), где »V(z) = тах{(И/к*(х), Wy’(y)}. Для каждого v = (х, у) е E-Tj- OUT, с х, у е Vt{x") или х, у е V, (j*)([w, v], г) в Qj 1 хранится непосредственно в Qj . проц DES(A/x,y, IN) = 1. для всех z с А/(у) - х таких что (у, z) е IN цикл 2. если И/(у) < w(y, z) то (MAXEDGE((z) W(z)) <- ((у, z), w(y, z)) 3. иначе (MAXEDGE(z), W(z)) «- (MAXEDGE(y), W(y)) все; 4 DFS(A/, y, z, IN) все все; проц EDGEFIND(A,'. p’, IN) = 1. DFS(A/, 0, p’, IN) все; проц ВЫЧИСЛЕНИЕ-ОЗ(А„ INy, OUT,,/ = (x’, у ), Qj."' = 1. (Qj , A/(x’), A/(y )) <- (0, A/x’) - {/}, A,(y ) - {X*}); 2. для всех x x* цикл A/(x) «- A/x) все; 3. для всех x e V цикл 4. если х е Ц(х”) то N(x) = 1 иначе N(x) := 0 все (И/-(х),И/-(х), MAXEDGE -(х), MAXEDGE -(х)<-(—»,-«>, 0, 0) Л У х У все;
Глава 2. Ориентированные деревья 171 5. Вызвать EDGEFINDfA/', х*. IN/) для получения MAXEDGE*- (х) и Wx-(x) для хеЦ(х*); 6. Вызвать EDGEFIND(A/ у', IN/) для получения MAXEDGEy- (у) и Wy-(y) дляуеЦ(х*); 7. для всех v = (х. у) из Е - 7) - OUT/ цикл 8 если Л/(х) = Л/(у) то 9. Добавить метку ([u,v], г) из Qi-1 к Qy 10. иначе добавить метку ([MAXEDGEw’fz), v], lV(v) - I/I4v (z)) к Q;, где z e {x, у} удовлетворяет соотношению Ww'(z) = max(Wx’(x), Wy'(y)) 11. % если Wiv*(z) = oo то метка не добавляется, т к. соответствующее ребро не существует % все все все 2.4.3. Поиск каркасов с заданными свойствами Среди приложений, особенно при конструировании сетей ЭВМ или сетей связи, встречается следующая задача: для данного взвешенного неориентированного графа найти каркас, у которого степень некоторой вершины г равна заданной константе, deg г= Ь, и который имеет наименьший вес среди всех таких каркасов. Идея решения состоит в последовательном применении элементарных преобразова- ний к некоторому начальному каркасу и, следовательно, в выборе начального каркаса и оптимальной последовательности элементарных преобразований. Пусть г— выделенная вершина в G и R— множество ребер, инцидентных г. Пусть 7*—множество всех каркасов с deg г ~ IT’n /?| = к. Нам нужно найти каркас из 7), с наименьшей возможной стоимостью. Заметим, что в общем случае для некоторого t> 1 Тк+0 в точности тогда, когда t < к < |Л|. Если Т — каркас с deg г = t, то для по- лучения каркаса с deg г = к могут быть добавлены любые к — t инцидентных г ребер (а другие ребра при этом должны быть удалены). Заметим, что t может быть строго больше единицы, если G I г несвязен. А. Если 7\ t + 0 и Т— оптимальное дерево в 7), то существуют ребра е е Т п R, fiTuR такие, что Т — e+f есть оптимальное дерево в Тк_\. Б. Если Ткхт0 и Т— оптимальное дерево в Тк, то существуют ребра е е Т Г\ R, f е R\T такие, что Т- e+f есть оптимальный каркас Tk+l В. Пусть Т— наименьший по весу каркас в Тк. Если ребра е е Т C\R и f T'cR вы- браны так, что Т — е -f— каркас и разность c(j) - с(е) — наименьшая для всех та- ких ребер, то Т -е + f— каркас с наименьшим весам в Тк । Мы можем найти сокращенное множество ребер, которое содержит наименьшие кар- касы во всех Тк. Для этого введем понятие лес-каркаса неориентированного графа, компоненты которого суть каркасы для каждой компоненты связности графа.
V72 Часть I. Обработка и визуализация графов Г. Пусть U — лес-каркас наименьшей стоимости для G — г. Тогда U о R содержит каркас с наименьшим весом в 7* при условии, что 7* Ф 0. Более общая задача состоит в построении оптимального каркаса, степень каждой вершины которого ограничена сверху. Построение каркаса с ограничениями на степень вершин. Алгоритм Габова Основная идея алгоритма состоит в отыскании оптимального каркаса, содержащего /?; потом применяются элементарные преобразования в соответствии со свойством 2.4.3, В для уменьшения степени deg г до Ь. Для ускорения вычислений найдем сна- чала минимальный лес-каркас U для G - г; потом нужно будет просмотреть только ребра из R о U в соответствии со свойством 2.4.3, Г. Для отыскания элементарных преобразований в соответствии со свойством 2.4.3, В используем систему очередей. Пусть Т — каркас на данном этапе вычислений. Рас- смотрим ребро ее Т n R. Элементарное преобразование, которое удаляет е из Т, до- бавляет ребро / соединяющее две компоненты связности графа Т- е. Очередь F(e) хранит все такие ребра f Приоритет f— это его вес с(/). Таким образом, ребро/ ко- торое может заменить е, находится достаточно легко. Очередь X хранит элементар- ные преобразования [e,fj, где для каждого ребра е е Тп R ребро f есть ребро с наи- меньшим весом, которое может заменить е. Приоритет преобразования [е,у] равен С(/) - с{е). Таким образом, легко находится оптимальное элементарное преобразова- ние. Алгоритм 2.6. Габова Дано. Граф G = (V, Е), вершина г, целое b (7/ а 0). Требуется. Каркас Т с наименьшим весом, для которого deg г — Ь. Метод. проц ГАБОВ = 1. Найти оптимальный лес-каркас U для G - г, % использовать алгоритм построения оптимального каркаса для каждой компоненты связности графа G - г % 2. R := множество ребер, инцидентных г 3. Удалить из G все ребра, не принадлежащие U и R, 4. Т := каркас с наименьшим весом, содержащий R; 5. X := пустая очередь с приоритетами; 6. для всех е из R цикл 7. F(e) := очередь с приоритетами, содержащая все ребра f е U. которые соединяют компоненты графа Т - е; 8. если F(e) ф 0 то 9. f:= наименьшее ребро в F(e); 10. Добавить [е/кХ все все
Гпава 2. Ориентированные деревья 173 11. пока deg г > b цикл 12. Удалить элементарное преобразование [е, с наименьшим весом из X; 13. Удалить Айз F(e); 14. Е' := ребро в R - е такое, что f соединяет компоненты графа Т- е'; 15. Удалить [е', f] из X; 16. Удалить f из F(e'); 17. Слить очереди F(e) и F(e’) в новую очередь с приоритетами F(e); 18. если F(e) * 0 то 19. F’ := ребро с наименьшим весом в F(e}; 20. Добавить [е‘, f] к X все, 21. T:=T-e + f все все Трудоемкость алгоритма — O(m log log n + n log ri), требуемая память — O(m + ri). Алгоритм легко модифицируется для решения задачи с ограничением вида deg r>b или deg г < b. Трудоемкость модифицированного алгоритма — С)(т log log и + n log ri). Евклидова задача Штейнера на плоскости Пусть на плоскости задано N точек (для простоты изложения будем считать N чет- ным). Проведем прямую L, разделяющую указанное множество точек на два: VL и VR. Соответствующие кратчайшие связывающие сети обозначим MST(P/) и MST(K/<). Что получится, если объединить эти деревья в одно? Очевидно, что самая левая часть дерева MST(K«) и самая правая часть дерева MST(F/J, вероятнее всего, останутся без изменения. Изменятся части деревьев, близкие к разделяющей прямой. Поэтому эф- фективная реализация процесса слияния деревьев является основой построения крат- чайшей связывающей сети методом "разделяй и властвуй". Процесс слияния включает два вида действий: добавление новых ребер для соедине- ния вершин деревьев MST(Kt) и М8Т(Г«) и удаление ребер указанных деревьев при образовании циклов. Чтобы избежать перебора всех возможных соединений между вершинами обоих деревьев, используется тот факт, что ребра искомого дерева явля- ются ребрами триангуляции Делоне, которая представляет собой фигуру, двойствен- ную диаграмме Вороного, откуда следует, что нужно перебирать только ребра триан- гуляции Делоне. проц КРАТЧАЙШАЯ-СВЯЗЫВАЮЩАЯ-СЕТЬ (V множество точек) = 1 Выбрать прямую X - L = 0 перпендикулярную оси ОХ такую, что NI2 точек, где N = |У|, имеют координату х меньше, чем L, а остальные NI2 точек — больше, чем L. Обозначить эти множества точек через и VR соответственно;
174 Часть I. Обработка и визуализация графов 2. КРАТЧАЙШАЯ-СВЯЗЫВАЮЩАЯ-СЕТЬ(\4); 3. КРАТЧАЙШАЯ-СВЯЗЫВАЮЩАЯ-СЕТЬ( Vr), 4. Найти ребра-кандидаты на соединение деревьев MST(14) и MST(Vr) из множества ребер триангуляции Делоне. Добавлять эти ребра к деревьям MST(Vj.) и MST(VR) поочередно снизу вверх. Если при этом образуется цикл, найти и удалить самое длинное ребро в цикле. все Подбор ребер-кандидатов (оператор 4) можно производить с разной эффектив- ностью, используя известные алгоритмы, например, из работы [99]. Отметим также, что построение кратчайшей связывающей сети на плоскости легко реализуется вручную. Трудоемкость алгоритма — O(N log N). Евклидова задача Штейнера в k-мерном пространстве Приводимый ниже алгоритм строит кратчайшую связывающую сеть для множества из N точек в А-мерпом евклидовом пространстве. Метод состоит в организации вна- чале N одновершинных фрагментов и повторении N-1 раз конструктивного шага, на котором выбирается фрагмент наименьшего размера и соединяется с ближайшим фрагментом. Структуры данных: □ А-с/-дерево точек для вычисления минимальных расстояний (описание структуры А-<7-дерева см. в гл. б); □ очередь с приоритетами фрагментов для выбора фрагментов, реализуемая как связный список (см. разд. 2.1.1)\ □ очередь с приоритетами минимальных расстояний до точек вне фрагмента; фор- мируется для каждого фрагмента и реализуется в виде 2-3-деревьев (см. гл. 6). начало 1. Построить оптимизированное A-d-дерево для множества точек; 2 для каждой точки р цикл 3. Образовать одновершинный фрагмент; 4. Образовать очередь расстояний все; % вначале каждый фрагмент содержит только одну вершину и не содержит ребер, каждая очередь расстояний содержит единственный элемент, обозначающий расстояние от точки до ближайшего соседа; чтобы избежать лишних вычислений, считаем вначале ближайшим соседом точки саму точку с расстоянием, равным 0 % 5. Образовать очередь фрагментов в виде очереди размеров фрагментов с приоритетами; % вначале очередь содержит Л/точек с приоритетами 1%
Глава 2. Ориентированные деревья 175 6 пока число фрагментов = 1 цикл % кратчайшая связывающая сеть построена, когда число фрагментов равно 1 % 7. Выбрать из очереди фрагментов фрагмент с наименьшим размером; 8. пока элемент с наивысшим приоритетом в очереди расстояний текущего минимального фрагмента нефиктивен цикл % когда вершина присоединяется к фрагменту, некоторые расстояния становятся фиктивными, т. е. ближайший сосед точки не лежит больше вне фрагмента % 9. X := первая вершина в очереди; 10 Y := ближайшая точка к X точка вне фрагмента; 11 Соединить X с У; 12. Удалить фиктивный приоритет вершины X и ввести заново нефиктивные приоритеты в очередь расстояний все; 13 X := первая вершина из очереди расстояний; 14. У := вершина, соединенная с X; 15. Слить очередь расстояний вершины X с очередью расстояний вершины У; 16. Включить ребро (X, У) во фрагмент, содержащий вершину У; 17. Обновить очередь размеров фрагментов путем удаления элементов, соответствующих прежним размерам фрагментов, содержащих X и У и добавления нового элемента соответствующего новому фрагменту содержащему У; все конец Трудоемкость алгоритма — (?(7V log N). Библиографический комментарий Предлагаемый в разд. 2.1 материал можно найти в большинстве монографий по теории графов. В основном мы ориентировались на монографии Ф. Харари и А. А. Зыкова. Операции над де- ревьями рассматривались в статье [2]. Результаты, связанные с представлением деревьев в виде кода Прюфера, взяты из статьи [1], оттуда же взято понятие оптимального кодирования. Кодирование деревьев с помощью обходов вершин наиболее полно рассмотрено в работе [13] и диссертации А. П. Завалы [12]. Описанные нами коды и представления деревьев рассматри- вались в работах [2, 39, 76, 99, 147, 148]. Следует также указать на препринт В. К. Попкова [27], посвященный этой тематике, а также на работу Д Кнута [17], где отдельный большой раздел посвящен деревьям, в частности прошитым деревьям, представлениям деревьев, в том числе представлениям произвольных корневых деревьев бинарными деревьями и пр. Различ- ные машинные представления деревьев рассмотрены в книге П. Холла [34]. Представление деревьев как графов данных было исследовано в работах А. Розенберга, их изложение и биб- лиографию можно найти в обзоре [10]. Материал разд 2.2.1 заимствован нами из монографий [11, 15], а алгоритмы обходов и генера- ции базируются на следующих работах: [137] - алгоритмы 2.2.6, 2.2.9 и 2.2.18; [75]— алго-
176 Часть I. Обработка и визуализация графов ритмы 2.2.7, 2.2.16; [134]— алгоритмы 2.2.8, 2.2.10, 2.2.11, 2.2.21—2.2.24; [17]— алгоритмы 2.2.13 и 2.2.14; [15]— алгоритмы 2.2.19 и 2.2.20; [126]— алгоритм 2.3.1; [148] — алгоритм 2.3.2; [99] — алгоритм 2 3.3; [146] — алгоритмы 2 3.4 и 2.3.9; [39] — алгоритм 2.3.5’ [143] алгоритм 2 3 6 [13] алгоритм 2.3.8. Методам представления сложноорганизованных данных в памяти вычислительной машины и создания программ со сложными структурами данных посвящены книги [4. 6. 16. 17, 22, 135]. В работе [77] рассматривается отличное от лексикографического линейное упорядочение на множестве всех кодов 2-3-дерсвьев с и внутренними вершинами Приводятся алгоритмы для определения номера кода в упорядоченном множестве и для построения кода по его номеру; каждый из алгоритмов занимает Оф) времени после некоторого шага предварительной обра- ботки, требующего О(и2) памяти и времени. Алгоритмы решения задачи генерации для fi-дсрсвьсв рассматриваются в [76]. В работе [101] решается проблема генерации, нахождения порядкового номера и восстановле- ния по номеру и-вершинных ЛВЛ-деревьев. Приводится код ЛК/7-дерева в виде двух целочис- ленных последовательностей, называемых ЛДП-последовательностями, и рассматривается линейное упорядочение на этих последовательностях. Приводятся алгоритмы нахождения порядкового номера и восстановления дерева по номеру за время Оф log2 ri) и Оф log2 ri), если до их применения выполнен шаг, требующий Оф2 log ri) времени. В статье [118] приводится способ кодирования бинарных деревьев последовательностями но- меров уровней их листьев, перечисленных слева направо, и описывается критерий того, что некоторая последовательность целых чисел является кодом бинарного дерева. Приводится алгоритм генерации списка всех кодов в лексикографическом порядке за линейное время от длины списка Описываются алгоритмы определения по коду его номера в списке, а также построения кода по его номеру в списке. Другие подходы к решению этих же задач рассматри- ваются в работах [60, 111, 115, 117, 146]. В работе 1139] рассматривается множество fc-арных деревьев на п вершинах, к > 2, п > 0, и лек- сикографический порядок на множестве перестановок, используемых для кодирования деревь- ев. Приводятся алгоритмы сложности Офк) для определения номера кода в упорядоченном множестве и построения кода по его номеру. Описывается алгоритм генерации всех кодов за линейное время от числа fc-арных деревьев на п вершинах. Статья [118] расширяет результаты, полученные в [119] для бинарных деревьев, на Парные деревья, fc-арное дерево с и листьями кодируется последовательностью из п номеров уровней листьев дерева. Приводится алгоритм генерации списка всех таких последовательностей в лексикографическом порядке, тратящий в среднем на один код О(к) времени. Строится алго- ритм сложности Оф) для определения номера кода в списке и построения кода по его номеру в списке. В работе [53] рассматривается задача конструирования по любой последовательности весов Wj. ..., w„ и целому числу t > 2 такого дерева Т с максимальной полустепенью исхода, не пре- вышающей t, и листьями V], v2, ..., v„, что минимизируется функция ..., w„) = max{/,+w,; zg [ 1 ; и]}, где I, обозначает длину пути по Тот корня до v,. Минимальное значение Дм>|, ..., и„) = min/z(W|, ..., w„) называется минимаксной длиной взвешенного пути. Найдена верхняя оцен- т ка дляДжь ..., в»,,) и построен эффективный алгоритм конструирования дерева, оптимального относительно минимаксной длины взвешенного пути Аналогичная задача для fc-арных деревь- ев решается в работе [92] Пусть р— вершина дерева Т. Удаляя р из Т вместе с инцидентными ей ребрами, получаем се- мейство поддеревьев {Tf,Ткр} и последовательность чисел р = (sh ..., л*) в которой л, обо-
Гпава 2. Ориентированные деревья 177 значает количество вершин в Tf. Пусть Г7 обозначает семейство последовательностей р , со- ответствующих вершинам Т. В работе [70] описываются полиномиальные алгоритмы ответа на следующие вопросы: дано семейство W последовательностей, образованных из строго поло- жительных целых чисел, существует ли свободное дерево Т, такое что Vr = W1 Если такое де- рево существует, имеются ли неизоморфные деревья 7\ и Т2 такие, что V1} = Г72 = W? На базе этих алгоритмов конструируется алгоритм для генерации всех неизоморфных деревьев Т, для которых Е7 = IV. Различные алгоритмы генерации равновероятных графов из разных классов содержатся в ра- ботах 112. 141]. Алгоритмы построения каркасов произвольного неориентированного графа заимствованы из книги [24] Первыми работами, в которых были предложены алгоритмы построения оптимальных карка- сов, были работы Краскала [96], Прима [114] и Дейкстры [56] (последние два алгоритма реали- зуют один и тот же подход и часто объединяются под именем алгоритма Прима — Дейкстры). Описание этих алгоритмов встречается в большинстве монографий по теории графов и прило- жениям; предлагаемый здесь алгоритм Краскала заимствован из книги [3] (см. [20]). Менее известен алгоритм Соллина. изложенный в книге [37]. Связь этих трех алгоритмов исследуется в работе [37] (см. [73, 91, 100, 110]). Следующая волна работ, посвященных данной задаче, связана с появлением алгоритмов с оценками трудоемкости. Среди них укажем на [49, 144], предложенные в этих работах алгоритмы имеют трудоемкость в худшем случае O(m log log и), в то время как алгоритм Прима, например, — О(п2). Развитием этого направления является использование новых типов структур данных. Так, использование деревьев в качестве струк- тур данных для реализации очередей с приоритетами дает вариант алгоритма Черитона — Тарьяна с трудоемкостью О(т log log(,„/„ +2j п), а использование в качестве структуры данных фиббоначиевой кучи улучшает эту оценку до О(т (3(пг, и)), где (3(от, и) = min {/ | log(,)H < т/п} [64]. В работах [66, 68] эта оценка улучшается до О(т log Р(»г. и)). Третья волна алгоритмов связана с появлением ин тереса к параллельным алгоритмам [97] и к алгоритмам для распреде- ленных вычислений [10], но это лежит за пределами нашей книги. В обзоре [74] утверждается, что алгоритм 11рима — Дейкстры есть на самом деле псреоткрытый алгоритм Ерника. пред- ложенный еще в 1930 г. [81]. Алгоритм построения оптимального оркаркаса принадлежит Эдмондсу [59] и излагается по книге [25]. Алгоритм построения оркаркаса с трудоемкостью О(т log п) был предложен также в работе [132]. Алгоритм проверки каркаса на оптимальность заимствован из работы [ 130]. Интерес к алгоритмам генерирования каркасов графов возник, по-видимому, в конце 50-х — начале 60-х гг. XX века в связи с исследованиями теоретико-графовых методов анализа элек- трических цепей [14, 44—46, 80, 86, 103—105, 108, 112, 113, 116, 140]. Лучшим из них по тру- доемкости считается алгоритм Габова и Майерса [69], его трудоемкость равна O{n + т + nt). Однако, хотя трудоемкость алгоритма Чара [44] в худшем случае равна O(n + т + n(t + т0)), Джаякумар и Тхуласирам [82], сравнивая его с алгоритмом Габова и Майерса, пришли к выво- ду о его большей эффективности, и это преимущество растет с ростом числа каркасов. Даль- нейшим развитием алгоритма Габова и Майерса является изложенный в данной главе алго- ритм Винтера с трудоемкостью O(n + т + nt) и требуемой памятью О(п2) [142]. Алгоритм генерирования оркаркасов принадлежит Чену [48], в его основе лежит алгебра Вана [37, 58, 140] Реализация алгоритма с помощью системы аналитических вычислений была вы- полнена А. Л. Семеновым (см. [30, 35, 122]). Оставляя в стороне матричные методы генерации каркасов [46, 47, 103], заметим, что наиболее эффективны методы генерации каркасов с использованием элементарных преобразований кар-
178 Часть I. Обработка и визуализация графов касов, причем именно те из них, которые основаны на преобразовании последнего построенно- го каркаса. Возможность существования таких алгоритмов вытекает из гамильтоновости графа каркасов данного графа (см. разд. 2.1.1), исследованной в работах [54, 78, 84, 94, 95, 124]. В связи с попыткой уменьшить трудоемкость алгоритма генерирования каркасов Майеды и Сешу [105] Део в 1960 г. ввел понятие центрального дерева графа. Оно оказалось чрезвычайно полезным при расчете электрических цепей с помощью законов Кирхгофа. Пусть /-[G] — ранг графа G = (К Е), т. е. ранг его матрицы смежности, и G S граф, получаемый из G удалением ребер из множества Е - S, S с Е. Део [55] определил центральное дерево графа G как каркас Ts, для которого справедливо неравенство r[G-Tv]<r[G’^], где Т— произвольный каркас графа G, Ts = Е - Ts и Т = Е-Т. Другое эквивалентное определение центрального дерева состоит в следующем [93, 125]. Пусть расстояние между каркасами определяется как наименьшее число элементарных преобразований, требующихся для перехода от одного каркаса к другому, и пусть Г — самый дальний для каркаса Т каркас. Пусть d(T) = | Т 7*|, где Т — дополнение к каркасу Т в G (кодерево). Тогда Т есть цен тральное дерево для G, если для него выполнено условие d(T) < d(T') для любого каркаса Г графа G. О других методах повышения эффективности генерации каркасов см. [83, 90, 121, 131]. Алго- ритм порождения каркасов в порядке возрастания их весов обычно имеет вид алгоритма, по- рождающего k-i\ по весу оптимальный каркас [85, 89, 98]. Излагаемый здесь алгоритм заимст- вован из работы [88]. Имея трудоемкость O(Km + min(n! log log п, и2), он представляет некото- рое усиление алгоритма Габова [39] с трудоемкостью О(Кта(т. п) + т log и), где а есть обратная по Тарьяну функция к функции Аккермана. Среди других работ на эту гему следует указать на [38, 40, 106]. Алгоритм с трудоемкостью О(и2) для решения задачи о каркасе наименьшего веса с ограниче- нием на степень выделенной вершины был предложен Гловером и Клингманом в работе [72], описываемый алгоритм Габова с трудоемкостью О(т log log п + п log п) заимствован из рабо- ты [65]. Задача построения кратчайшей связывающей сети для Р точек на евклидовой плоскости (или Р точек в Л-мсрном евклидовом пространстве) известна как евклидова задача Штейнера. Впер- вые она была поставлена как геометрическая задача (см. [14, 21, 71, 107]), в которой нужно множество точек Р на евклидовой плоскости соединить линиями так, чтобы сумма длин отрез- ков была минимальна. Если не допускаются пересечения любых двух линий в точках вне за- данного множества Р, то задача сводится к одной из задач нахождения оптимального каркаса эквивалентного графа на вершинах с матрицей весов, вычисленных как евклидово расстояние между точками множества Р. Если допускается на плоскости введение дополнительных "ис- кусственных" вершин (называемых точками Штейнера), то длину кратчайшей связывающей сети можно уменьшить соответствующим подбором точек. Таким образом, для решения зада- чи Штейнера можно добавить в любых местах плоскости столько точек Штейнера, сколько необходимо для построения наикратчайшего дерева, стягивающего множество из Р точек. По- лучающееся дерево называют наикратчайшим деревом Штейнера. Задача Штейнера на евкли- довой плоскости достаточно хорошо изучена, и известно большое число свойств наикратчай- шего дерева Штейнера [20, 51—52, 71, 107]. Бентлей и Фридман [36] предложили два алгоритма для решения евклидовой задачи Штейнера и показали, что в среднем ее трудоемкость равна О(п log и) В работах [87, 108] были предло- жены улучшенные версии этого алгоритма, а в [87] указывалось, что в худшем случае трудо- емкость алгоритма Бентлея и Фридмана равна О(п log п). В работе [123] показано, что мини- мальное связывающее дерево на плоскости может быть извлечено из диаграммы Вороного для заданных точек на плоскости. Трудоемкость предложенного там алгоритма— О(п logn) в худшем случае. В работе [145] предложен алгоритм для отыскания кратчайшей связывающей
Глава 2. Ориентированные деревья 179 сети в A-мерном пространстве с трудоемкостью O(n2~a^ (log n)'~"w), где a(k) = Эта оцен- ка может быть улучшена до О((п log и)18) для трехмерного пространства. Описанный алгоритм построения с трудоемкостью О(п log п) основан на использовании триангуляции Делоне и за- имствован из работы [42]. Алгоритм с такой же трудоемкостью описан также в [127]. Из других задач, связанных с каркасами, укажем на следующие. Пусть дан граф и каркас в нем и пусть веса ребер произвольно изменяются. Возникает задача исследования чувствительности каркаса к изменениям весов, решение ее рассмотрено в работе [133]. Другая интересная задача состоит в эффективном преобразовании оптимального каркаса в оптимальный же при измене- нии весов ребер Этой задаче посвящены, например, работы [50, 63, 129]. В [63] предлагается новая структура данных, использование которой в задаче генерирования каркасов во взвешен- ном графе снижает трудоемкость до O(m log log(2 + m/„)H + А2 2 -yfrn ) при к = 0(2 уГт ). Пусть теперь в графе G = (К, Е) задано подмножество вершин V а И и пусть Т' есть оптималь- ный каркас для подграфа G' = (//’, Ег), V" < Н'< V, причем вес каркаса Т' наименьший среди всех таких каркасов для подграфов, обладающих указанным свойством. Данная задача извест- на как задача о минимальной связке, или задача Штейнера на графах. Ее связь с рядом задач теории графов (число всссмежности, неплотность и др.) была исследована В. Г. Визингом в работе [5], алгоритмы решения предложены в [23, 43, 57, 79, 96]. Однако с вычислительной точки зрения эти алгоритмы являются неэффективными процедурами, хотя они и значительно лучше, чем последовательный просмотр оптимальных каркасов всех подграфов графа. Список литературы 1. Анисимов А. В. Об оптимальной упаковке деревьев // Кибернетика. — 1976. № 3.— С. 89— 91. 2. Анисимов А. В., Карпенко И. В., Крижановский В. В. Представление упорядоченных деревьев// Там же.— 1980.— № 3.— С. 29—34. 3. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. — М.: Мир, 1978. 4. Берзтисс А. Т. Структуры данных. — М.: Статистика, 1974. 5. Визинг В. Г. Сводимость ряда задач теории графов к задаче о минимальной связке И Вы- числительная математика и вычислительная техника.— Харьков, 1971.— Вып. 2.— С. 52—55. 6. Вирт Н. Алгоритмы + структуры данных = программы. — М.. Мир, 1985. 7. Гудман С., Хидетниеми С. Введение в разработку и анализ алгоритмов. — М.: Мир, 1981. 8. Гэри М., Джонсон Д. Вычислительные машины и труднорешасмые задачи. — М.: Мир, 1982. 9. Евстигнеев В. А. Графы адресуемых данных // Комбинаторно-алгебраические методы в прикладной математике. — Горький, 1986. — С. 39—60. 10. Евстигнеев В. А. О некоторых свойствах локальных алгоритмов на графах И Комбинатор- но-алгебраические методы в прикладной математике. — Горький, 1983. — С. 72—105. II. Евстшнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки деревьев. — Ново- сибирск: Наука, 1994. 12. Завала А. П. Исследование средних оценок вычислительной сложности алгоритмов обра- ботки структур данных типа дерева: Автореф. дис. ... канд. физ.-мат. наук: 05.13.11.-— Киев, 1987.
180 Часть I. Обработка и визуализация графов 13. Завада А. П, Кожевникова Г. П. К анализу алгоритмов над деревьями. Векторные коды. Генерация случайных структур и характеристика дерева // Кибернетика.— 1984.— №5, —С. 12—18. 14. Зыков А. А. Теория конечных графов. — Новосибирск: Наука. Сиб. отд-ние, 1969. — 4.1. 15. Касьянов В. Н. Оптимизирующие преобразования программ. — М.: Наука, 1988. 16. Касьянов В. Н., Сабельфельд В. К. Сборник заданий по практикуму на ЭВМ. — М.: Наука, 1986. 17. Кнут Д. Искусство программирования для ЭВМ. — М.: Мир, 1976. — Т. 1. Основные ал- горитмы. 18. Кожевникова Г. П. Структуры данных и проектирование эффективной вычислительной среды. — Львов: Вища шк., 1986. 19. Кокстер Г. С. М. Введение в геометрию. — М.: Наука, 1966. 20. Кристофидес Н. Теория графов. Алгоритмический подход. — М Мир, 1978 21. Курант Р., Роббинс Г. Что такое математика? — М.: Наука, 1970. 22. Лавров С. С., Гончарова Л. И. Автоматическая обработка данных, хранение информации в памяти ЭВМ. — М.: Наука, 1971. 23. Левин А. Ю. Алгоритм кратчайшего соединения группы вершин графа // Докл. АН СССР. — 1971. — Т. 200. № 4. — С. 773—776. 24. Липский В. Комбинаторика для программистов. — М.. Мир, 1988. 25. Майника Э. Алгоритмы оптимизации на сетях и графах. — М.: Мир. 1981. 26. Непомнящий В. А., Дехтярь М. И. Математическая теория программирования. Обзор за- рубежных работ. — Новосибирск, 1982. — 52 с. — (Препринт / АН СССР. Сиб. отд-ние, ВЦ; № 341). 27. Попков В. К. Представление деревьев. — Новосибирск, 1981. — 26 с. — (Препринт/ АН СССР, Сиб. отд-ние, ВЦ; № 242). 28. Рейнгольд Э., Нивергельт Ю., Дсо Н. Комбинаторные алгоритмы: теория и практика. М.: Мир, 1980. 29. Риордан Дж. Введение в комбинаторный анализ. — М.: Изд-во иностр, лит., 1963. 30. Семенов А. Л. Программа обработки графов на ЭВМ с использованием системы аналити- ческих вычислений и ее применения // Методы и программы решения оптимизационных задач на графах и сетях. — Новосибирск, 1984. — Ч. 1. — С. 204—206. 31. Слисенко А. О. Сложностные задачи теории вычислений // Успехи мат. наук. — 1981. — Т. 36, №6,—С. 21—103. 32. Успенский В. А., Семенов А. Л. Теория алгоритмов: основные открытия и приложения. — М.: Наука, 1987. 33. Харари Ф., Палмер Э. Перечисление графов. — М '- Мир, 1977. 34. Холл П. Вычислительные структуры. Введение в нечисленное программирование. — М.: Мир, 1978. 35. Яблонский Г. С., Евстигнеев В. А., Быков В. И. Графы в химической кинетике// Приме- нение теории графов в химии. — Новосибирск, 1988. — С. 70—143. 36. Bentley J. L., Friedman J. Н. Fast algorithms for constructing minima] spanning trees in coordi- nate spaces // IEEE Trans. Computers. — 1978. — Vol. C—27, N2. — P. 97—105.
Глава 2 Ориентированные деревья 181 ЗУ. Berge С., Ghouila-Houri A. Programme, Spiele, Transportnctze. — Leipzig: В. G.Teubner Ver- lagsgeselschaft, 1967. 38. Berger L, Nathan A. The algebra of sets of trees, К-trees and other configurations//IEEE Trans. Circuit Theory. — 1968. — Vol. CT-15, N 3. — P. 221—228. 39 Beyer T., Hedetniemi S. M. Constant time generation of rooted trees // SIAM J. Comput. — 1980. Vol. 9, N 4, —P. 706—712. 40 Burns R. N., Haff С. E. A ranking problem in graphs // Proc, of the 5th Southwest Conf, on Combinatorics, Graph Theory and Computing. — 1974. — P. 461—470. 41 Camerini P. M., Fratta L . Maffioli F. The К shortest spanning trees of a graph // Int. Rep 73— 10, IEEE-LCE Politcchnico di Milano. — Milan, 1974. 42 Chang R. C, Lee R. С. T. An O(nlogn) minimal spanning tree algorithm for n points in the plane//BIT. — 1986. — Vol. 26, N 1. — P. 7—16. 43. Change S.-K. The generation of minimal trees with Steiner topology // J. ACM. —• 1972 Vol. 19.— P. 699 44 Char J. P. Generation of trees, two-trees and storage of master forests // IEEE Trans. Circuit Theory. — 1968, —Vol. СТ-15, —P. 128—138. 45 Chase S M. Analysis of algorithms for finding all spanning trees of a graph // RS3190, IBM T. J.Watson Research Center, Yorktown Heights, N. Y., 1970. 46 Chen Wai-Kai, Li H.-C. Computer generation of directed trees and complete trees // Int. J. Elec- tronics. — 1973. — Vol. 34. — P. 1. 47 Chen Wai-Kai. Applied graph theory. — Amsterdam, North-Holland, 1971. 48. Chen Wai-Kai. On directed trees and directed К-trees of a digraph and their generation // J. SIAM Appl. Math — 1966. — Vol. 14, N 3. — P 550—560. 49. Cheriton D., Tarjan R. E. Finding minimum spanning trees // SIAM J. Comput. — 1976. — Vol. 5, N 4. — P. 724—742. 50. Chin F., Houck D. Algorithm for updating minimum spanning trees // J. Comput. System Sci. — 1978, —Vol 16.—P. 333—334. 51. Cockayne E. J. On the efficiency of the algorithm for Steiner minimal trees И J. SIAM Appl. Math.—1970. —Vol. 18. —P 150. 52. Cockayne E. J., Melzak Z. A. Steiner's problem set terminals // Quart. Appl. Math. —1968. — Vol. 26, —P. 231 53. Coppersmith D., Klawe M. M., Pippenger N. J. Alphabetic minimax trees of degree at most t // SIAM J. Comput. — 1986. -Vol. 15,N L —P. 189—192 54. Cummings R. L. Hamilton circuits in tree graphs // IEEE Trans, on Circuit Theory. — 1966. — Vol. CT-13 P. 82. 55. DeoN. On central tree // IEEE Trans. Circuit Theory. — 1960. — Vol. CT-13. — P. 439—440. 56 Dijkstra E. W A note on two problems in connection with graphs // Numer. Math. — 1959. Vol. L —P. 269—271. 57 Dreyfus S. E., Wagner R. A. The Steiner problem in graphs // Networks. —1972. — Vol. 1. -— P. 195. 58 Duffin R. J. An analysis of Wang algebra of network // Trans. Am. Math. Soc. — Oct. 1959. — P. 114—130.
182 Часть I. Обработка и визуализация графов 59. Edmonds J. Optimum branchings. Mathematics of the decision sciences // Leet. Appi. Math. — 1968. — Vol. 2. — P. 346—361. 60. Er M. C. Enumerating ordered trees lexicographically // Comput. J. — 1985. — Vol. 28, N 5. — P. 538—542 61. Farrell E. J. Spanning trees in graphs with cyclomatic numbers 2, 3 and 4 // .1. Combinatorics, In- form. and Syst. Sci — 1980. — Vol. 5, N 1. — P. 38—46. 62. Fidler J. K., Horrocks D. N. On the generation of K-trees // J. of Electronics.— 1973.— Vol. 34. —P. 185. 63. Frederickson G. N. Data structures for on-line updating of minimum spanning trees, with appli- cations // SIAM J. Comput. — 1985. — Vol. 14, N 4. — P. 781—798. 64. Fredman M. L., Tarjan R. E. Fibonacci heaps and their uses in improved network optimization algorithms // J ACM. 1987. — Vol 34, N 3. — P. 596—615. 65. Gabow H. N. A good algorithm for smallest spanning trees with a degree constraint // Net- works. — 1978 — Vol 8, —P. 201—208 66. Gabow H. N. Efficient algorithms for finding minimum spanning trees in indirected and directed graphs // Combinatorica. — 1986. — Vol. 6, N 2. — P. 109—122. 67. Gabow H. N. Two algorithms for generating weighted spanning trees in order И SIAM J. Com- put. — 1977. — Vol. 6. — P. 139—150. 68. Gabow H. N., Galil Z., Spencer T. Efficient implementation of graph algorithms using contrac- tion// Proc 25th Annual IEEE Symp on Foundations of Computing — New York, 1984. — P. 338—346. 69 Gabow H N., Myers E. W. Finding all spanning trees of directed and undirected graphs // SIAM J. Comput. — 1978. — Vol. 7. — P. 280—287 70. Gavril F., Schonheim J. Constructing trees with prescribed cardinalities for the components of their vertex deleted subgraphs// J. Algorithms. — 1985. — Vol. 6, N 2. — P. 239—252. 71. Gilbert E. N., Pollack H O. Steiner minimal trees// .1. SIAM AppL Math.— 1968.— Vol. 16. —P. 1. 72. Glover F„ Klongman D. Finding minimum spanning trees with a fixed number of links at a node // Rep. N 74-5, Res. Rep. CS 169, Center for Cybern. Studies. — Austin, Texas, 1974. 73. Gower J. C , Ross G J S. Minimum spanning trees and single linkage cluster analysis // Appl. Statistics. — 1969. — Vol. 18. — P. 54. 74. Graham R. L., Hell P. On the history of the minimum spanning tree problem // Ann. Hist. Com- put. — 1985. —Vol. 7,N 1. — P. 43—57. 75. Gries D. The Schorr-Waite graph marking algorithm // Acta Informatica. — 1979. — Vol. 11, Fasc. 3. — P. 223—232. 76. Gupta L). L., Lee D T., Wong С. K. Ranking and unranking of B-trees // J. Algorithms. — 1983. Vol. 4, N L — P. 11—60. 77. Gupta U. L., Lee D T., Wong С. K. Ranking and unranking of 2-3-trees // .1. Algorithms. — 1982. —Vol. 11,N3 — P. 582—590. 78. Hakimi S. L. On trees of a graph and their generation // J. Franklin Inst. — 1961. — Vol. 272, N5. — P. 347—359. 79. Hakimi S. L. Steiner's problem in graphs and its implications// Networks.— 1971.— Vol. L —P. 113
Гпава 2. Ориентированные деревья 183 80 Hakimi S. L., Green D. G. Generation and realization of trees and k-trees // IEEE Trans. Circuit Theory. — 1964. — Vol. CT-11. — P. 247—255. 81 Jamik V. О jistem problemu minimalnim// Praca Moravske Prirodovcdske Spolecnosti.— 1930. — Vol. 6. — P. 57—63 (на чешек, яз.). 82. Jayakumar R., Thulasiram K. Analysis of a spanning tree enumeration algorithm // Combina- torics and Graph Theory. Leet. Notes in Math. — Springer-Ver!., 1980. — N 833. — P. 284— 289. 83 lohnson D. B. Priority queues with update and finding minimal spanning trees // Inf. Process. Lett.— 1975.—Vol. 4,N1. 84 Китае T. The existence of Hamiltonian circuits in tree graphs// IEEE Trans. Circuit The- ory. — 1967. — Vol. CT-14. —P. 279. 85 Kano M. Maximum and k-th maximal spanning trees of a weighted graph // Combinatorica. — 1987. — Vol. 7. — P. 205—214. 86. Kasahara Y. et al. Topological evaluation of system determinants// TechnoL Repts. Osaca Univ. — 1962. — Vol. 12. — P. 239—248. 87. Katajainen J. On the worst case of a minimal spanning tree algorithm for euclidean space // BIT.— 1983. —Vol. 23, N I. —P. 2—8. 88. Katon N., Ibaraki T., Mine H. An algorithm for finding k minimum spanning trees // SIAM J. Comput. — 1981. — Vol. 10, N 2. — P. 247—255. 89. Kawamoto T., Kajitani Y., Shinoda S. On the second maximal spanning trees of a weigted graph //Trans. IECE Japan. — 1978. — Vol. 61-a — P. 988—995. 90. Kershenbaum A., Van Slyke R. Computing minimum spanning trees efficiently// Proc. Ann. Conf ACM. — Boston. 1972. — P 518. 91. Kevin V., Whitney M. Algorithm 422 — minimal spanning tree // Comm. ACM. — 1972. — Vol. 15. — P. 273. 92. Kirkpatrick D. G., Klawe M. M. Alphabetic minimax trees// SIAM J. Comput.— 1985.— Vol. 14, N 4. — P. 514—526. 93. Kishi G., Kajitani Y. Generalized topological degree of freedom in analysis of LCR networks // Papers of the Techn. Group on Circuit and System Theory of Inst. Elec. Comm. Eng. Japan, NCT71—19, July 1971. —P. 1—13. 94. Kishi G., Kajitani Y. On Hamilton circuits in tree graphs // IEEE Trans. Circuit Theory. — 1968. —Vol. CT-15 — P. 42. 95. Kishi G., Kajitani Y. On the realization of tree graphs // Ibid. — P. 271. 96 Kruscal J. B., Jr. On the shortest spanning subtree of a graph and the travelling salesman prob- lem//Proc. Amer. Math. Soc. — 1956. — Vol. 7. — P. 48—50. 97 Lavallec 1., Roucairol G. A fully distributed (minimal) spanning tree algorithm // Inf. Process. Letters. — 1986. — Vol. 23, N 2. — P. 55—62. 98. Lawler E. L. A procedure for the computing the k best solutions to discrete optimization prob- lems and its application to the shortest path problem// Manag. Sci.— 1972.— Vol. 18.— P. 401—405. 99 Lee С. C., Lee D. T., Wong С. K. Generating binary trees of bounded bight // Acta Infor- matica. — 1986. — Vol. 23, N 5. — P. 529—544. 100 Lee D. T., Schachter B. J. Two algorithms for constructing Delaunay triangulations // Int. J. Comput. and Inform. Sci. — 1980. — Vol. 9, N 3. — P. 219—242.
184 Часть I. Обработка и визуализация графов 101 Li L. Ranking and unranking AVL-trees// SIAM J. Comput. 1986.— Vol. 15, N 4.— P. 1025—1035. 102. Loberman H., Weinberger A. Formal procedures for connecting terminals with a minimum total wire length // J. ACM. — 1957. — Vol. 4. — P. 428. 103 Maycda W. et al Generation of complete trees// IEEE Trans. Circuit Theory.— 1968.— Vol. CT-15. — P. 101. 104 Mayeda W. Graph Theoty. — New York. Wiley-Intersci., 1972. 105. Mayeda W., Sehu S. Generation of trees without duplications // IEEE Trans. Circuit Theory. — 1965, —Vol. CT-12. —P. 181—185. 106. Mayr E. W., Plaxton C. G. On the spanning trees of weighted graphs// Leet. Notes Comp. Sci. — 1989. — Vol. 344. — P. 394—405. 107. Melzak Z. A. On the problem of Steiner// Canad. Math. Bull. —-1961. — Vol. 4. — P. 335. 108. Minty W. A simple algorithm for listing all the trees of a graph// IEEE Trans. Circuit The- ory. — 1965. — Vol. CT-12, N 1. — P 120. 109. Neveiainen O., Ernvall J., Katajaincn J. Finding minimal spanning trees in a euclidean space // BIT. — 1981. —Vol 21, N 1. 110. Obrica A. Algorithm 1- mintree // Computer Bull. — 1964. P. 67. 111. Pallo J M. Enumerating, ranking and unranking binaty trees//Comput. J. 1986. — Vol 29. N2. —P. 171—175. 112. Paul A. J., Jr Generation of directed trees and 2-trees without duplication // IEEE Trans. Cir- cuit Theory. — 1967. — Vol. CT-14. — P. 354. 113. Piekarski M. Listing of all possible trees of linear graph// IEEE Trans. Circuit Theory.— 1965.—Vol. CT-12, N 1.— P. 124—125. 114. Prim R. C. Shortest connection networks and some generalizations// Bell System Tech. J. — 1957. —Vol. 36. —P. 1389—1401. 115. Proskurowski A. On the generation of binary trees// J. ACM.— 1980.— Vol. 27, N L — P. 1—2. 116. Read R. C., Tarjan R. E. Bounds on backtrack algorithms for listing cycles, paths and spanning trees // Networks. —-1975. — Vol. 5. — P. 237—252 117. Rotem D., Varol Y. L. Generation of binary trees from ballot sequences // J. ACM. 1978. — Vol 25, N3. — P 396—404. 118. Ruskey F. Generating t-ary trees lexicographically// SIAM J. Comput.— 1978.— Vol. 7, N4.-P. 424—439. 119. Ruskey F., Hu T. C. Generation binary trees lexicographically// Ibid.— 1977.— Vol. 6, N 4. — P. 745—758. 120. Schorr H., Waite W. M. An efficient machine independent procedure for carbage collection in various list structures // Comm. ACM. — 1967. — Vol. 10, N 8.— P. 501—506. 121. Scott A. Combinatorial programming, spatial analysis and planning.— London: Methuem, 1971. 122. Semenov A. L., Mel'nikov L. S., Evstigneev V. A. Solving the problems of kinetics of reactions by symbolic algebraic manipulation methods // J. Symbolic Computation. — 1987. — N 3. — P. 303—307.
Глава 2. Ориентированные деревья 185 123. Shamos М. I., Hoey D. Closest point problem// 16th Ann. IEEE Symp. on Foundations of Comput. Sci., 1975. — P. 173 -186. 124. Shank H. Note on Hamilton circuits in tree graphs // IEEE Trans. Circuit Theory. — 1968. — Vol. CT-15.— P 86. 125. Shinoda S., Kawamoto T On central trees of a graph// Leet. Notes Comp. Sci.— 1981.— Vol. 108, —P. 137—151. 126. Skarbek W. Generating ordered trees// Theor. Comp. Sci.— 1988.— Vol. 57, N 1.— P. 153—159 127. Smith J. M., Lee D. T., Liebman J S. An O(NlogN) heuristic for Steiner minimal tree problems on the Euclidean metric//Networks.— 1981. — Vol. 11, N I.—P. 23—29 128. Solomon M., Finkel R. A. A note on enumerating binary trees // J. ACM. — 1980. — Vol. 27, N L — P. 3—5. 129. Spira P. M., Pan A. On finding and updating spanning trees and shortest paths // SIAM J. Com- put. — 1975. — Vol. 4, N 3. — P. 375—380. 130. Tarjan R. E. Applications of path compression on balanced trees// J. ACM.— 1979.— Vol. 26.— P. 690—715. 131. Tarjan R. E. Data structures and networks algorithms// Soc. for Industr. and Appl. Math. — 1983. 132. Tarjan R. E. Finding optimum branchings // Networks. — 1977. — Vol. 7. — P. 25—35. 133. Tarjan R. E. Sensitivity analysis of minimal spanning trees and shortest path trees // Inf. Proc. Lett. — 1982. — Vol. 14, N 1. — P. 30—33. 134. Tarjan R. E. Space-efficient implementation of graph search methods // ACM Trans. Math. Software. — 1983. — Vol. 9, N 3. — P 326—339. 135. Tarjan R. E., Van Leeuwen J Worst-case analysis of set union algorithms // J. ACM. 1984. — Vol. 31, N 2. — P. 245—281. 136. Temo J. Complexity des Minimalgerustes// 24 Intern. Wiss. Roll./ TH Ilmenau, 22.10 — 26.10.1979. — 1979. — Bd 2,3, Heft 5. —P. 23—25. 137. Thorelli L. E. Marking algorithms // BIT. — 1972. — Vol. 12, N 4. — P. 555—568. 138. Trent H. M. A note on the enumeration and listing of all possible trees in a connected linear graph // Proc. Nat. Acad. Sci. U.S.A. — 1954. — Vol. 40. — P. 1004 139. Trojanowski A.E. Ranking and listing algorithms for k-ary trees // SIAM J. Comput. — 1978. — Vol. 7, N 4. — P. 492—509. 140. Wang К. T. On a new method for the analysis of electrical networks // Not. Res. Inst. Eng. Acad. Sinica.— 1934 —M. 2.— P. 1—11. 141. WilfH. S. The uniform selection of trees// J. Algorithms. — 1981. — Vol. 2, N 1 - P. 204— 207. 142. Winter P. An algorithm for the enumeration of spanning trees// BIT.— 1986.— Vol. 26, N L — P 44—62. 143. Wright R. A. et al Constant time generation of free trees// SIAM J. Comput.— 1986.— Vol. 15, N 2. — P. 540—548. 144. Yao A. C. An O(EloglogV) algorithm for finding minimum spanning trees // Inf. Proc. Lett. — 1975, —Vol. 4, —P. 21—23.
186 Часть I. Обработка и визуализация графов 145. Yao А. С. On constructing minimal spanning trees in k-dimensional space and related prob- lems И SIAM J. Comput. — 1982. — Vol. 11, N 4. — P. 721—736. 146. Zaks S. Generation and ranking of k-ary trees// Inf. Process. Lett. — 1982. — Vol. 14, N I. — P. 44—48. 147. Zaks S. Lexicographic generation of ordered trees// Theor. Comp. Sci. — 1980.— Vol. 10, Nl.-P. 63—83 148. Zerling D. Generating binary trees using rotations// J. ACM.— 1985.— Vol. 32, N 3.— P. 694—701.
ГЛАВА 3 Бесконтурные графы Глава содержит основные определения, свойства и алгоритмы, касающиеся следую- щего за деревьями по важности класса ориентированных графов— бесконтурных (или, как еще говорят, ациклических) графов. В англоязычной литературе для графа изданного класса употребляется аббревиатура DAG. 3.1. Основные свойства и алгоритмы Рассмотрим основные свойства дэгов и базовые алгоритмы их обработки. 3.1.1. Основные свойства и подклассы Бесконтурным называется ориентированный граф, не содержащий контуров. Напомним, что контур — это замкнутый путь в орграфе, т. е. такая последователь- ность вершин и дуг vo(vo, Vi) Vi — Vi (vi, v/+I) v;+I... v„, что: □ для всех i, 0 < i < n -1, (v„ v,+I) есть дуга в орграфе; о VO=V„. Из определения вытекает, что все дуги контура одинаково ориентированы относи- тельно выбранного направления обхода (рис. 3.1). В отличие от контура замкнутая последовательность дуг, произвольно ориентированных относительно некоторого направления обхода, часто называется циклом (рис. 3.2). В силу этого замечания другое, достаточно широко используемое название этого ти- па графов— ациклический граф (англ, acyclic graph)— не совсем удачно. Многие специалисты, занимающиеся графами, считают неудачным внедрение в русский язык термина дэг (англ. DAG — directed acyclic graph), появившегося в связи с частым употреблением английской аббревиатуры DAG в литературе. Дэг называется связным, если для любой пары вершин v и w существует цепь (после- довательность дуг, произвольно ориентированная относительно направления движе- ния от v к и'), ведущая из г в гг. Так, граф на рис. 3.3 связен, а 1раф на рис. 3.4 — несвязен, он состоит из трех компо- нент связности.
188 Часть I. Обработка и визуализация графов Рис. 3.4. Несвязный дэг Вершина бесконтурного графа, в которую не заходит ни одна дуга, называется вход- ной вершиной, или просто входом. В графе на рис. 3.3 вершины 1, 3, 5 и 6 суть входы. Аналогично, вершина, из которой не выходит ни одна дуга, называется выходной вершиной, или просто выходом. В графе на рис. 3.3 вершины 7 и 8 — выходы. Бесконтурный граф называется корневым, если у него в точности один вход (назы- ваемый в этом случае корнем графа). Примером корневого бесконтурного графа мо- жет служить корневое растущее ордерево (рис. 3.5). Последовательность попарно не смежных вершин в связном бесконтурном графе называется антицепью. В графе на рис. 3.3 последовательность вершин <2, 4, 7> об- разует антицепь. А. Бесконтурный граф содержит хотя бы одну входную вершину и хотя бы одну выходную вершину. Из наличия входной и выходной вершин вытекают следующие свойства. Б. Матрица смежности бесконтурного графа содержит хотя бы одну нулевую строку и один нулевой столбец. В. Вершины бесконтурного графа могут быть разбиты на непересекающиеся под- множества Ио, И,,..., V„ так, что все дуги имеют вид (у, и'), где v G И,-,, a w G Б,, j > i,i=\,...,n.
Глава 3. Бесконтурные графы 189 Рис. 3.5. Корневое растущее дерево Г, Вершины бесконтурного графа могут быть занумерованы следующим образом: I. Номер начала дуги строго меньше номера ее конца, т. е. для дуги (j,j) име- ет место неравенство i < j. 2. Номер начала дуги строго больше номера ее конца, т. е. для дуги (i,j) имеет место неравенство i > j. Д. Вершины бесконтурного графа могут быть занумерованы так, что его матрица смежности имеет вид либо 1-й верхней, либо 2-й нижней треугольной матрицы Нумерация вершин, соответствующая условию 1 в свойствах 3.1.1, Г и Д, называется топологической сортировкой вершин', нумерация, соответствующая условию 2, — обратной топологической сортировкой. Топологическая (обратная топологическая) сортировка F дэга, минимизирующая не- который функционал W(F), называется его укладкой. Пусть G = (V, Е)— корневой бесконтурный граф. Тогда поиск в глубину G, начиная с корня, разбивает множество дуг графа на три класса: древесные, прямые и попереч- ные. С другой стороны, объединение множеств древесных, прямых и поперечных дуг произвольного орграфа образует остовный бесконтурный суграф данного графа, на- зываемый носителем исходного графа. Е. Носитель орграфа определяется однозначно, если в орграфе не существует мно- говходовых контуров, т. е. контуров с двумя или более вершинами, в которые захо- дят дуги извне контура. Множество вершин В бесконтурного графа называется его вершинной базой, если каждая вершина, не входящая в В, достижима из некоторой вершины в В и В мини- мально в том смысле, что никакое собственное подмножество В этим свойством не обладает. Ж. В бесконтурном графе есть единственная вершинная база, состоящая из всех его входных вершин. Множество вершин А бесконтурного графа называется его вершинной контрабазой, если из каждой вершины графа можно достичь некоторой вершины в А и А мини- мально в указанном выше смысле.
190 Часть I. Обработка и визуализация графов 3. В бесконтурном графе есть единственная вершинная контрабаза, состоящая из всех его выходных вершин. Число арк помеченных бесконтурных графов с р вершинами и к входами удовлетво- ряет соотношению иЧ ' Пусть в ряде а(х, у) коэффициент при хк равен арк. Тогда несколько первых чле- нов ряда а(х, у) даются выражением а(х, у) = х + х2 + 2ху + х3 + 9х3 у + 15х/ + х4 + + 28х3 у + 198х2 / + 316х/ + х5 + 75х4 у + + 1610х2/ + 16885а/+ .... Бесконтурный граф называется складным (collapsible) орграфом, если он может быть преобразован в тривиальный (состоящий из единственной вершины) граф некоторой последовательностью применения следующих трех преобразований: Т1. Удаляется дуга (х,у) и вершина у, если |ЗАХОД(у)| = 1 и |ИСХОД(у)| = 0. Т2. Удаляются дуги (х, у), (y,z), вершина у и добавляется дуга (х, z), если |ЗАХОДу)| = |ИСХОД(у)|=1. ТЗ. Если имеется две дуги, соединяющие вершину х с вершиной у, то удаляется одна из них. Примеры применения преобразований показаны на рис. 3.6—3.8. Пример складного графа приведен на рис. 3.9. Два преобразования Т2 и ТЗ, взятые отдельно (без ТЗ), определяют последовательно- параллельные (series-parallel) графы, введенные Риорданом и Шенноном. Одно пре- образование Т1 порождает древовидные подграфы. Рассмотрим линейный по сложности алгоритм, который, обрабатывая корневой би- нарный бесконтурный граф, нормально останавливается тогда и только тогда, когда исходный граф является складным. Рис. 3.6. Преобразование Т1
Гпава 3. Бесконтурные графы 191 Рис. 3.7. Преобразование Т2 Рис. 3.9. Складной граф
192 Часть I. Обработка и визуализация графов Алгоритм 3.1 Дано. Ациклический граф G с входом р. Требуется. Проверить, является ли складным граф G. Метод. проц ПОИСК(и : вершина) = 1. Пометить и как "старая"; S(u) := 0; 2. если и — лист то возврат 3. иначе для всех е = (и, у) е ИСХОД (и) цикл 4. если у имеет пометку "новая" то ПОИСК (у) все; 5. если ЧЗАХ (у) = 1 то Це) := S(y) иначе Це) := у все все; 6. Пусть ev = (и, и) и е» = (и, и/) — дуги, исходящие из и (если ИСХОД (и) = {ev}, то конструируется фиктивная дуга е» с Це„) = 0); 7. если L(ev) = 0 то S(u) := Це„) 8. иначе если Це„) = 0 то S(u) := L(ev) 9. иначе если L(ev) + L(ew) то G не складной 10. иначе z := L(ev); 11. ЧЗАХ (z) := ЧЗАХ (z) — 1; 12. S(u) := если ЧЗАХ (z) > 1 то z иначе S(z) все все все все все; начало 1. для всех вершин графа v цикл 2. Пометить v как "новая"; 3. 43AX(v):= | ЗАХОД (v)| все 4. ПОИСК (р); 5. если S(p) + 0 то G не складной иначе G складной все конец Значение S(x) для вершины х имеет следующий смысл. Равенство S(u) нулю при воз- врате из вершины и означает, что подграф с корнем и исходного бесконтурного графа является складным. Если S(u) имеет ненулевое значение, то S(u) представляет верши- ну, ближайшую к и, в которую заходит дуга извне подграфа с корнем и. Чтобы весь граф был складным, любая другая вершина подграфа с корнем и, в которую заходит дуга извне, должна доминироваться с вершиной S(u). Пусть и — вершина с дугами ev = (и, v) и е„, = (и, м>). Дуги е„ и е„, обрабатываются симметрично. Дуга ег обрабатывается, как только становится известно, что вершина v "просмотре- на". Если v имеет более одной дуги, заходящей в нее, т. е. v все еще разделяется, то L(ev) устанавливается равным v. Иначе £(е,,) становится равным S(v). Таким образом,
Глава 3. Бесконтурные графы 193 L(eJ указывает, имеется ли "необнаруженная" разделяемая вершина в подграфе с корнем v. Если £(<?,.) = 0, то подграф с корнем v складывается в единственную вершину, так что v вкладывается в и с помощью трансформации Т1. Иначе, если £(е„) # 0, но £(е„.) = О, то имеется цепь и, v, L(ev), где v будет элиминирована с помощью трансформации Т2. Наконец, если £(е„) = /_(е„,) ф 0, то алгоритмом найдены два пути из и в £(е,), которые складываются с помощью трансформации ТЗ. 3.1.2. Топологическая сортировка Топологическая сортировка строится следующим простым алгоритмом Алгоритм 3.2. Топологическая сортировка Дано. Ациклический граф G. Требуется. Топологическая сортировка графаG. Метод. процТопСорт1(б : граф)= 1. л := 1; 2. пока G содержит вершины цикл 3. Пусть V— множество всех входных вершин графа; 4. Занумеровать в произвольном порядке вершины из V числами от л до п + |У]’ 5. Удалить из графа все вершины из множества V вместе с инцидентными им дугами; 6. л:=л + |У| все все Нетрудно заметить, что данный алгоритм дает и обратную топологическую сорти- ровку, если вместо входов брать выходы. Следующий алгоритм строит топологическую сортировку вершин на основе обхода графа в глубину. Алгоритм 3.3. Топологическая сортировка Дано Ациклический граф G. Требуется. Топологическая сортировка графа G. Метод. проц НОМЕР(л, и)= 1. если все дуги, заходящие в и, помечены, то 2. Присвоить v номер л; 3. л := л + 1; 4 если из v выходит непомеченная дуга (v, w) то 5. Пометить дугу (v, w); 7 Зак. 202
194 Часть I. Обработка и визуализация графов 6. HOMEP(n, w); все 7 иначе Выбрать произвольную непомеченную дугу (f и); 8. если t не имеет номера то 9. НОМЕР(л, Г) 10 иначе Пометить дугу (и f), 11. НОМЕР(л, и); все все все; проц ТопСорт2(б : граф)= 1 л;=1; 2. Пусть V— множество незанумерованных вершин; 3. пока I/ не пусто цикл 4. Пусть v — произвольная вершина из V; 5. НОМЕР(л, и); все все На рис. 3.10 и 3.11 представлены два способа построения топологической сорти- ровки. Для графа, заданного списками смежности ПРЕЕМ[т], v е V, алгоритм построения топологической сортировки может иметь следующий вид. Алгоритм 3.4. Топологическая сортировка Дано. Ациклический граф G. Требуется. Топологическая сортировка ТграфаG Рис. 3.10. Топологическая сортировка алгоритмом 3.1
Глава 3. Бесконтурные графы 195 Рис. 3.11. Топологическая сортировка алгоритмом 3 2 Метод. процТопСортЗ(О : граф)= 1. для всех v е V цикл 43AX[v] := 0 все; 2. % 43AX[v] = число дуг, заходящих в v % 3 для всех и е V цикл 4. для всех v еПРЕЕММ Цикл 43AX[v] := 43AX[v] + 1 все; все; 5. СТЕК ;= 0; 6 для всех v е V цикл 7 если 43AX[v] = 0 то СТЕК <= v все все 8. N := 0; 9. пока СТЕК Ф 0 цикл 10. и := Э СТЕК; 11. N - N +1; T[u] = N; 12. для всех v е. ПРЕЕМ[о] цикл 13. 43AX[v] := 43AX[v] — 1; 14 если 43AX[v] = О то СТЕК <= v все все все все Так как каждая дуга анализируется алгоритмом 3.4 один раз в строке 4 и один раз в строке 12, то сложность алгоритма есть О(т) (если m = Q(«)) или в общем случае 0(т + и).
196 Часть I. Обработка и визуализация графов 3.1.3. Кратчайшие пути Пусть G = (К, £)— взвешенный бесконтурный орграф, вершины которого занумеро- ваны в соответствии с топологической сортировкой, есть вход графа, d(v,, v,) — вес (длина) дуги (v„ у,) и ставится задача найти кратчайшие пути из г, во все остальные вершины, т. е. пути с наименьшей суммой длин составляющих их дуг. Задача состоит из двух подзадач: задачи из вычисления кратчайших расстояний от V| до остальных вершин и определения собственно кратчайших путей. Первая из них решается сле- дующим алгоритмом в предположении, что граф G задан списками предшественни- ков ПРЕД[у|. Алгоритм 3.5. Кратчайшие расстояния Дано. Ациклический граф G и его вершина v,. Требуется. Кратчайшие расстояния от вершины V| во все вершины графа G. Метод. проц Расстояние^, Vi)= 1. D[vi]:=O; 2. % D[u,j — кратчайшее расстояние между vi и и %; 3. для j от 2 до л цикл D[vJ := со все; 4. для у от 2 до п цикл 5. для всех V, е ПРЕД[у,] цикл 6. D[y] := min(D[vJ, О[и] + d(v„ Vj)) все все все Так как каждая дуга анализируется в строке 6 в точности один раз, сложность алго- ритма есть О(т). Собственно кратчайший путь в графе находится по следующему правилу "обратного хода". Пусть требуется найти кратчайший путь из v, в и уже известно расстояние £>[v,] от Vi до v,. Вершины пути [vb v,] = [vb v2,..., v,_b v,] отыскиваются в порядке v,_b v,_2 и т. д., причем в качестве г,., берется вершина у, для которой выполняется равенство £>[>’] = - d(y, vi) в качестве вершины v,_2— вершина w, для которой выполняется равенство D[w] = - d(w, v,_f) и т. д. 3.1.4. Критический путь Алгоритм поиска кратчайших расстояний может найти применение в методах управ- ления выполнением проекта, называемых PERT (Project Evaluation and Review Technique) или CPM (Critical Path Method), а также в методах оптимизации циклов при распараллеливании программ. Эти методы основываются на построении граф- модели проекта {сети PERT или сети СРМ), дуги которой соответствуют некоторым
Глава 3. Бесконтурные графы 197 элементарным задачам, составляющим проект, а их веса указывают на время, необ- ходимое для решения отдельных задач. Кроме того, мы предполагаем, что для произ- вольных дуг этого графа (и, v) и (v, t) задача, изображаемая дугой (и, v), должна быть закончена перед началом решения задачи, изображаемой дугой (v, t). Легко заметить, что такой граф должен быть бесконтурным. Решение задачи планирования управле- нием выполнения проекта состоит в отыскании самого длинного (критического) пути в граф-модели проекта из вершины s, соответствующей началу проекта, до вершины (, соответствующей его окончанию. Длина критического пути определяет время, не- обходимое для реализации всего проекта. Задача об отыскании критического пути сводится к задаче о кратчайшем пути и ре- шается алгоритмом из предыдущего раздела путем изменения знака каждого веса (/(и, v) дуги (w, v) на обратный. 3.1.5. Путевое покрытие Пусть G— бесконтурный орграф с входом s и выходом /. (Общий случай графа с не- сколькими входами и выходами легко сводится к рассматриваемому путем добавле- ния фиктивных входа и выхода.) Путевым покрытием вершин графа G называется совокупность Р s-z-путей такая, что каждая вершина принадлежит хотя бы одному пути из совокупности Р. Покрытие Р называется минимальным, если никакое собственное подмножество его покрытием уже не является. Назовем множество .S' вершин графа G несравнимым (независимым), если для любой пары вершин vh vj из S справедливо утверждение: ни v, не достижима из Vj, ни v7 не достижима из vh Пусть/,(G)— мощность наибольшего несравнимого множества вершин в G, и пусть p,.(G) наименьшее число путей, необходимых для покрытия вершин G. Имеет ме- сто следующее утверждение. К. Для любого бесконтурного графа iv(G) = pv(G). Построение путевого покрытия вершин: метод минимального потока Потоковой сетью называется орграф (необязательно бесконтурный) с входом s и выходом I, каждой дуге и которого приписаны два целых положительных числа: с[й)— (верхняя) пропускная способность и г(и) — нижняя пропускная способность, О < г(и) < фи). На потоковой сети можно определить поток мощности Ф (см. гл. 1). При этом нас будет интересовать поток f мощность которого наименьшая среди всех потоков, удовлетворяющих нижним пропускным способностям дуг. Такой поток называется минимальным потоком. Для сведения задачи о построении путевого покрытия к задаче о минимальном пото- ке преобразуем бесконтурный орграф в потоковую сеть следующим образом. Расще- пим каждую вершину v, отличную от 5 и t, на две вершины v' и v" и добавим дугу (и', к') (рис. 3.12).
198 Часть I. Обработка и визуализация графов Рис. 3.12. Расщепление вершины Припишем каждой дуге вида (у', v") нижнюю пропускную способность r(v', v") = I. а для остальных дуг сети, т. е. дуг исходного графа, положим г = 0. Будем считать так- же, что с(и) = оо для всех дуг сети. Полученную таким образом сеть обозначим G/; Б. Если f—минимальный поток по сети GjU Ф — его величина, то pv(G) = zv(G) — Ф. Построение путевого покрытия: метод наибольшего паросочетания Пусть G = (A'LJ У, Е)— двудольный орграф. Подмножество Е' дуг орграфа G, не имеюших общих вершин, называется паросочетанием. Паросочетание с наибольшим числом дуг для данного G называется наибольшим (максимальным) паросочетанием вб. Для сведения задачи о путевом покрытии к задаче об отыскании наибольшего паро- сочетания построим для данного бесконтурного графа G = (V, U)c\V\ = п двудольный орграф G = (V', U'), в котором И' = X О Y = {хь ..., х„} О {уь ..., у,,} и (х„уф е U' то- гда и только тогда, когда v; достижима из v, в G. Справедливо свойство. В. Пусть G = (V, Е) — бесконтурный орграф, G = (V', Е1) — соответствующий дву- дольный орграф, и пусть W— наибольшее паросочетание в G. Тогда p,(G) = /V(G) = H-|B1 Таким образом, трудоемкость данного метода определяется трудоемкостью исполь- зуемого им алгоритма для нахождения наибольшего паросочетания. 3.2. Транзитивное замыкание и транзитивная редукция Одними из основных операций над ациклическими графами являются операции на- хождения транзитивного замыкания и транзитивной редукции. 3.2.1. Необходимые определения Напомним, что бинарное отношение на некотором множестве есть набор упорядо- ченных пар элементов этого множества. Транзитивное замыкание бинарного отно- шения R есть отношение R*, определенное следующим образом: xR'y тогда и только тогда, когда существует такая последовательность х0=х,х1,2,—, хк=у, что к>0 и x0Rx[,xlRx2,-;Xll_iRxk.
Глава 3. Бесконтурные графы 199 Ясно, что xRy => xR*y. Следовательно, R сГ' Отношение R* также является наи- меньшим транзитивным отношением, включающим R. Таким образом, если R тран- зитивно, то R' = R. Бинарное отношение R на множестве X изображается орграфом, вершины которого представляют элементы множества X, а дуги — упорядоченные пары элементов, оп- ределяющие отношение R. На рис. 3.13 приведено представление отношения "явля- ется собственным делителем" на множестве Х= {2, 3,4, 6, 9}. Пусть G — ориентированный граф, представляющий отношение R. Орграф G*, пред- ставляющий транзитивное замыкание R* отношения R, называется транзитивным замыканием графа G. Из определения R* следует, что дуга (v, w), v w, принадлежит R* тогда и только то- гда, когда в графе G существует путь из v в w, т. е. когда w достижима из v. Анало- гично, петля (v, v) принадлежит графу G* тогда и только тогда, когда в G существует контур, содержащий v. Рис. 3.13. Граф отношения быть собственным делителем Определим матршру достижимости R(G) графа G на п вершинах как п х п (0, ^-мат- рицу, в которой элемент (/,у) равен 1 тогда и только тогда, когда вершина j достижи- ма из вершины i. Очевидно, что: А. Матрица смежности транзитивного замыкания G* графа G является в то же время матрицей достижимости графа G. Рассмотрим следующий пример. Пусть граф G имеет матрицу смежности, изобра- женную на рис. 3.14. Тогда матрица достижимости G и матрица смежности G* будут иметь вид, представленный на рис. 3.15. 0 10 0 0 0 0 0 10 0 0 0 110 Рис. 3.14. Матрица смежности графа G
200 Часть I. Обработка и визуализация графов Транзитивное замыкание G* 0 10 0 0 10 0 0 0 0 0 0 0 0 0 110 0 110 0 1110 1110 Рис. 3.15. Матрица достижимости графа G и матрица смежности графа G' соответственно Граф G называется транзитивной редукцией графа G, если его транзитивное замыка- ние изоморфно транзитивному замыканию графа G, т. е. G* = G*. Граф Gr называется минимальной транзитивной редукцией графа G тогда и только тогда, когда G* — G* и не существует собственного подграфа G, графа G такого, что g; = g;. 3.2.2. Алгоритм Уоршалла Этот алгоритм находит матрицу достижимости R путем вычисления последователь- ности квадратных матриц В0, В1,.... В” порядка п в соответствии со следующими пра- вилами. функ Уоршалл (G : граф)= 1. B°.= A(G)\ 2. для / от 1 до п цикл 3- В':=В'1 + [В'/1&В;-1| все; 4. R := В?; 5. возврат R все Заметим, что начальный шаг В0 := A(G) соответствует случаю достижимости вершин с помощью путей без промежуточных вершин, l-й шаг— с помощью путей, содер- жащих в качестве промежуточных вершины из множества {п,..., v/}. Трудоемкость алгоритма Уоршалла — О(п3). 3.2.3. Общая форма алгоритма Уоршалла Замкнутым полукольцом называется система (5,+, •, О, I), где S— множество эле- ментов, а "+" и — бинарные операции на S, обладающие следующими пятью свойствами; 1. (S,+, 0)— моноид, т е. множество S замкнуто относительно операции "+’ (а + Ь 6 S для всех а и b из 5), операция "+" ассоциативна и 0 служит единичным элементом (а + 0 = 0 + а = а для всех а из S). Тройка (S, •, 1) также является моно-
Глава 3. Бесконтурные графы 201 идом. Кроме того, предполагается, что 0 служит аннулятором, т. е. а • 0 - = 0*а = 0. 2. Операция "+" коммутативна и идемпотентна (а + а = а). 3. Операция дистрибутивна относительно 4. Если <?[, а2, ..., at — счетная последовательность элементов из S, то сумма Oi + а2 +...+ а, +... существует и единственна. Более того, ассоциативность, комму- тативность и идемпотентность выполняются не только для конечных, но и для бесконечных сумм. 5. Операция дистрибутивна не только относительно конечных, но и относительно счетных сумм (это не следует из свойства 3). Таким образом, из свойств 4 и 5 вы- текает, что & =£(а/Л)=Е • V ' )\l J 'J ' V J > Для а е S положим /=0 где а0 = 1 и d = а • а'1. Эта унарная операция называется замыканием. Свойство 4 гарантирует, что а е S. Из свойств 4 и 5 вытекает равенство а* = 1 + а • а . Отметим, что 0’ = Г = 1. Пусть в орграфе G = (E, £) дуги помечены элементами некоторого замкнутого полу- кольца (S, +, 0, 1). Определим метку пути как произведение меток дуг, составляю- щих этот путь, причем метки берутся в порядке прохождения дуг. В частности, метка пути нулевой длины равна 1 (единичному элементу для оперании’умножения рас- сматриваемого полукольца). Для каждой пары вершин (у, w) определим с(у, и>) как сумму меток всех путей между v и w. Назовем c(v, w) стоимостью прохождения из v в». Условимся считать, что сумма по пустому множеству путей равна 0 (единичному элементу для операции "+" нашего полукольца). Заметим, что если G имеет контуры, то между v и w может быть бесконечно много путей, но аксиомы замкнутого полу- кольца гарантируют, что c(v, w) определяется корректно. Пусть /: (Их И)->5, где (S, +, -, 0, 1) — замкнутое кольцо, причем I (v„ у,) = 0, если (v(, v,) g Е. Алгоритм 3.6. Алгоритм Уоршапла общего вида Дано Граф G, дуги которого помечены элементами некоторого замкнутого полу- кольца (S, +, -, 0, 1). Требуется. Стоимости с(у, w) прохождения из v в w для всех вершин графа G.
202 Часть I. Обработка и визуализация графов Метод. проц Уоршалл2= 1. для /от 1 до п цикл С° := 1 + /(ц, к) все; 2. для всех 1 <i,j<nu i*jцикл С° := /(к, V,) все; 3. для к от 1 до л цикл 4. для всех 1 <i,j£n цикл с _z~>k—1 z^k—1 /z*>k—1 z^k—1 □. Ujj .-Lry +^ik Ipkk / '^kj все все; 6. для всех 1 < i, j < n цикл c (v,, vt) := Cft все, все Рассмотрим замкнутое полукольцо Si = ({0, 1}, +, , 0, 1), где сложение и умножение соответственно заданы в табл. 3.1. Таблица 3.1. Операции сложения и умножения тк __ s-tk—X . z~«k—I х'чк—I ij ^ik ^kj ' Чтобы вычислить рефлексивно-транзитивное замыкание графа, достаточно взять следующую функцию разметки: ,, ч [1, если (v.,v.)— дуга графа G, /(Vj ,¥, ) = <„ 7 7 [0, в противном случае. При этом стоимость с(у, w) равна 1 тогда и только тогда, когда из v в w идет путь длины 0 или больше. 3.2.4. Алгоритмы Горальчиковой-Коубека и Симона Будем предполагать, что бесконтурный граф G = (И, Е) топологически отсортирован, т. е. если (7,у) е Е, то i < j, и что списки смежности ПРЕЕМ[у] = {w 6 Е\ (у, w) е Е} упорядочены в возрастающем порядке. Это может быть сделано за линейное время О(И + |£|)-
Гпава 3. Бесконтурные графы 203 Введем ряд определений. Говорят, что вершина w принадлежит рефлексивно-транзитивному замыканию ПРЕЕМ’М! тогда и только тогда, когда существует путь из v в w в G. Множество ПРЕЕМ/-[г] = {тг е ПРЕЕМ[у] | не существует пути длиной по крайней мере 2 из v в tv} называется транзитивной редукцией вершины v. В этом разделе мы будем использовать следующие обозначения: Е* — множество дуг транзитивного замыкания, ;п* = |Е*|, Ег— множество дуг транзитивной редукции, тг = | Er|, y(v) = |ПРЕЕМ [v]|, у’ (v) = |ПРЕЕМ’[у]|, у,. = |ПРЕЕМ'[г]|. Пусть IlPEEMfv] = {tv, < W2 < ... < w,.}; тогда имеем ПРЕЕМ»] = {v} о ПРЕЕМ’М1] о ПРЕЕМ’[тг2] о ... о ПРЕЕМ’М»]- Дпя топологически отсортированного орграфа имеют место включения wtg ПРЕЕМ ' [v] о tv, g nPEEM’Mi] о ... о nPEEM’[Tv,_,] <Е> ПРЕЕМ’М/] с ПРЕЕМ’М] о ... о ПРЕЕМ'М,]. Отрицание этого соотношения дает ПРЕЕМ'М = {tv, е ПРЕЕМ[т’]| tv, g ПРЕЕМ’М,] о - ПРЕЕМ’М,_,]} и, далее, |JnPEEM*M] = |JnPEEM’[z] меПРЕЕММ zeFlPEEM'[v] Алгоритм 3.7. Горальчиковой-Коубека Дано. Топологически отсортированный бесконтурный граф G = (P, Е), в котором списки смежности ПРЕЕМ[v] = М g K|(v, tv)gE} упорядочены в возрастающем порядке. Требуется. Стоимости с(у, тг) прохождения из v в tv для всех вершин графа G. Метод. проц Горальчиковой-Коубека = 1. для v от л до1 цикл 2. ПРЕЕМ» := {V}; 3. ПРЕЕМ» := 0; 4. для всех w е ПРЕЕМ[и] в порядке возрастания цикл 5. если w g ПРЕЕМ’ [v] то 6. ПРЕЕМ» := ПРЕЕМ» и ПРЕЕМ»]; 7. ПРЕЕМГ(v] - ПРЕЕМ» и {и/} все все все все
204 Часть I. Обработка и визуализация графов Внутри цикла 2—7 используется битовый вектор для представления ПРЕЕМ’М, так что проверка "w е ПРЕЕМ [v]" имеет трудоемкость 0(1). Вне этого цикла мно- жество ПРЕЕМ* [v] хранится в виде списка. Отсюда следует, что операция (ПРЕЕМ’М vj ПРЕЕМ’М]) имеет трудоемкость О(и) и, следовательно, общая трудо- емкость равна О(л mr). Алгоритм Симона состоит в улучшении способа вычисления объединения ПРЕЕМ’М VJ ПРЕЕМ’М]. Разбиение Z,, ..., Z* множества вершин (Z, 0 для всех 1 < i < к и Z, VJ ... vj Z*. = I'') называется цепным разложением графа G тогда и только тогда, когда каждая цепь Z„ 1 < i < к, есть путь в G. Так как граф G топологически отсортирован, то для пути Z, = М < ... < vj имеем (v„ v,+i)e Е для всех у, 1 <j <s. Число к называется шириной разложения. Цепное разложение Z,, ..., Zk порождает отображения- □ id (id(v) = z <=> v е Z,); □ niv, (niv, (Z) = min (Л n Z7), A с E); □ niv (niv(/4) = { vj niv, (Z)| 1 <j < k}). Будем использовать обозначение niv,(v) для niv,(nPEEM‘M) и niv(v) для niv(nPEEM’M)- Кроме того, предполагаем, что А = ПРЕЕМ’М,] ПРЕЕМ’М?] ПРЕЕМ’Мл], и поэтому A n Z, есть путь в G с первой вершиной niv, (А). Использование цепного разложения для ускорения вычисления транзитивного замы- кания основано на утверждении ПРЕЕМ’М = (J {w е Z,| w > niv, (v)}. Вычисление niv, (v) основано в свою очередь на утверждении [min({niv М) I w е ЗАПИСЬ МВ), если j * id(v), niv(v) = ] 1 [у, в противном случае. проц Вычисления цепного разложения = 1. /:=1; 2. для всех ve V цикл id(v) = 0 все; 3. И = V; 4 пока И * 0 цикл 5. х := min (И); Z := {х}; 6. пока Э у g V, с(х, у) g Е цикл 7. Пусть у есть наименьшее из у g V, таких, что (х, у) е Е\ 8. Z := Z + {у}; х := у все, 9. Z,:=Z; := И-Z; 10 для V v g Z, цикл zd(v) := / все;
Гпава 3. Бесконтурные графы 205 11. /:=/+1. все все Рассматривая цепное разложение, подразумеваем, что оно построено рассмотренным методом. В процедуре вычисления niv(v) используется список nivlist [v] для хранения величин niv(v); nivfield и id — массивы целых чисел. проц Вычисление niv = 1. для s от1 до к цикл nivfield [s] := оо все; 2 для v от л до 1 цикл 3. ПРЕЕМ'[v] := 0; nivlist [v] := 0; 4. для всех w е flPEEMfv] в порядке возрастания цикл 5. если w < nivfield[id[w]] то 6. ПРЕЕМ' [V] := ПРЕЕМ' [v] и {и}; 7. для всех р е nivlist[w] цикл 8. nivfield [кВД] = min (nivfield [id[p]], р) все все все; 9. nivfield[id[v']] := v; 10. для s от 1 до к цикл 11. если nivfield[s] * «> то 12 nivlist[V] := nivlist[V] u nivfieldfs] все; 13. nivfield[s] := <» все все все Таким образом, алгоритм Симона получается из алгоритма Горальчиковой-Коубека заменой операции ПРЕЕМ’М := ПРЕЕМ’М о ПРЕЕМ'М на niv[nPEEM*[v]] := niv[nPEEM’[v] о ПРЕЕМ’[и ]] Трудоемкость алгоритма Симона— О(т* + т к), где к— мощность цепного разло- жения. 3.2.5. Алгоритм Жомард-Мину Данный алгоритм предназначен для эффективного отыскания транзитивного замыка- ния бесконтурного орграфа, заданного списками смежности. Его трудоемкость равна 0(т, и), что делает целесообразным его применение для разреженных графов, у ко- торых число дуг много меньше гГ.
206 Часть I. Обработка и визуализация графов Заметим, что случай произвольного орграфа легко сводится к рассматриваемому путем отыскания бикомпонент и перехода к фактор-графу (графу Герца) относитель- но множества бикомпонент. Пусть G = (И, Е)— исходный бесконтурный граф, и пусть вершины его занумерова- ны в обратном топологическом порядке, т. е. (|,у) е Е =>j < i. В основе алгоритма лежит следующая идея. Каждой вершине / е V сопоставляется список L„ который в конце вычислений будет содержать все вершины, достижимые из i. Эти списки вначале содержат прямых потомков вершины i. Окончательные спи- ски будут последовательно формироваться в порядке возрастания номеров вершин, с использованием того факта, что когда на текущем шаге начинается обрабатываться вершина к, списки ее прямых потомков j е ГА: уже готовы в окончательном виде. Алгоритм 3.8. Жомард-Мину Дано. Бесконтурный граф G = (V,E) с вершинами, занумерованными в обратном топологическом порядке, заданный списками смежности ПРЕЕМ[/], / = 1, ..., 7V(=|P|)- Требуется. Транзитивное замыкание G*, определяемое списками смежности £[/]. Метод. Состоит из двух последовательных шагов: Инициализация: L[1] <- ПРЕЕМ[1] = 0, £[2] <- ПРЕЕМ[2] Основной шаг: для к от 3 до Л/ цикл L(k) <- ПРЕЕМ[к] L[/l /еПРЕЕМ[И все Эффективная реализация этого алгоритма зависит от способа реализации операции слияния списков на основном шаге. Если списки £[/] представлены в виде 0—1 векторов р, длины = 1 <=> вершина к принадлежит списку £[/]), то проверка вершины к требует O(N |ПРЕЕМ[£]|) элемен- тарных операций, а общая сложность алгоритма равна G(|£|-|P|). Трудоемкость предложенного алгоритма может быть понижена за счет более эффек- тивной реализации операции слияния списков. 3.2.6. Быстрый алгоритм слияния списков Пусть нам нужно получить список £[£] путем слияния списка ПРЕЕМ[А] со списками £[/] для j < к, представленных в форме линейного массива S, адресуемого указателем Р(-) следующим образом. Список £[/] потомков вершины j(j < к) располагается в мас- сиве 5 между индексами /’(/) и P(j + 1)- 1. На шаге к массив 5 содержит списки £[1],..., L[k - 1] между индексами 1 и Р(к) (Р(к) было определено в тот момент, когда последний потомок вершины к — 1 был занесен в массив S). Проблема теперь состоит в определении значения Р(к+ 1) и сохранении списка по- томков вершины к в массиве 5 между индексами /’(А) и Р(к+ 1)- 1. Для этого мы
Гпава 3. Бесконтурные графы 207 будем использовать вспомогательный массив С (размера 7V*), представляющий спи- сок L[k] и построенный в виде связанного списка, и скалярную величину D, удовле- творяющие следующим соглашениям: □ D есть индекс первого элемента в списке (если список не пуст); £> = —!, если спи- сок пуст; □ С(/) * 0, если элемент j принадлежит списку, и С(/) = 0 в противном случае; П если С(/) строго больше нуля, то С(/) обозначает индекс следующего элемента в списке, С(/) = -1 обозначает, что j — последний элемент списка. На этой структуре данных реализуются следующие две операции: (01)— проверить, что элемент j уже в списке; (02) — включить новый элемент в список. Обе эти операции могут быть выполнены за время 0(1). (Предполагаем, что не нужно беспокоиться о порядке элементов в списках; проблема значительно усложнилась бы, если бы нужно было строить упорядоченные списки потомков.) Чтобы реализовать операцию (О1), достаточно проверить, имеет ли место неравенст- во С(/) 0 (если С(/) = 0, элемента j еще нет в списке). Чтобы реализовать операцию (02), т. е. включить в список элемент у, отсутствующий в списке (С(/) = 0), нужно проделать следующее: □ присвоить значение D позиции j массива С (С(/) <- £)); □ переобозначить элемент j как новый первый элемент списка (О <— у). После того как мы последовательно проверили все элементы списков ПРЕЕМ[&] и L/J е ПРЕЕМ[Л]) (модифицируя каждый раз С и D, когда находится элемент, еще не представленный в С), построим список Lk (без избыточности, т. к. каждый элемент встречается не более одного раза) в виде связанного списка за ( х О |ПРЕЕМ[А:]| + < /еПРЕЕМ[*]> элементарных операций. Информация, содержащаяся в (С, О), потом преобразуется в обычный список и хра- нится в массиве S путем просмотра всех ненулевых элементов в С за О(|Е|) элемен- тарных операций. Одновременно массив С очищается для подготовки к следующей итерации. В целом число элементарных операций, необходимых для построения полного спи- ска потомков вершины к в транзитивном замыкании, равно (\ |Л4| + |ПРЕЕМ[*]| + Х1Л/1 УеПРЕЕМ[Л]^
208 Часть I. Обработка и визуализация графов Суммируя по к от 1 до 7V, получаем оценку О £ ЧЗАХ[А] + М + 22 ЧЗАХ[Л] ЧВЫХТР[£] = \ к к J = О 22чЗАХ[Л] • ЧВЫХТР[£] , где ЧЗАХ [А] — число дуг, заходящих в вершину к (полустепень захода), ЧВЫХТРИ — число дуг, исходящих из вершины к (полустепень исхода) в транзи- тивном замыкании, М— число дуг в графе. 3.2.7. Определение транзитивного замыкания и транзитивной редукции при неполностью известной матрице смежности В ряде приложений, например в вычислительной геометрии, матрица смежности графа апрори не известна, но любой элемент может быть вычислен по мере необхо- димости. Если трудоемкость этого вычисления достаточно велика, возникает про- блема организации вычислений без лишних операций определения элементов матри- цы смежности. Рассмотрим простой алгоритм 3.9 с трудоемкостью О(/?3), на основе которого строит- ся экономный алгоритм. Оба алгоритма— последовательные, работают с бесконтур- ными графами; на шаге s алгоритмов определяются транзитивное замыкание и тран- зитивная редукция подграфа G, = (И„ (а,Д„,), где P,={vi, —, у,}. Алгоритм 3.9 Дано. Бесконтурный граф G = (P,E) с вершинами, занумерованными в обратном топологическом порядке, заданный списками смежности ПРЕЕМ[г], /'= 1, ..., 7V(=|P]). Требуется. Транзитивное замыкание и транзитивная редукция G. Метод. для s от 2 до п цикл % Ч а с т ь А: Вычисление последнего столбца в матрицах Cs (матрица смежности транзитивного замыкания) и Rs (матрица смежности транзитивной редукции) % % Определение непосредственных предшественников вершины Vs % 1. IP := 0; 2 для / от 1 до s цикл 3. если А(/, s) = 1 то 4. 1Р:=1Рш{1}, R(i, s):=1;C(/, s):=1; все все 5. для всех / е IP в порядке возрастания цикл
Глава 3. Бесконтурные графы 209 % Редукция последнего столбца матрицы Rs % 6. для всех t е IP, t ф /, в порядке возрастания цикл 7. если C(t, /) = 1 то R(f, s) := 0 все; все, % Вычисление единичных элементов в последнем столбце матрицы Cs % 8 для всех t от 1 до s - 1 отличных от i цикл 9. если C(t, /) = 1 то С (t, s) := 1 все все все % Ч а ст ь В Вычисление последней строки матриц Rs и Cs. ==========Реапизуется аналогично части А-========= % % Ч а с т ь С Редукция Rs-i и вычисление единиц в Cs_-i % 1 ДЛЯ I ОТ 1 ДО S - 1 цикл 2 , для всех j от 1 до $ - 1 отличных от / цикл 3 . если С(/, s) = C(s, j) = 1 то R(J, j) :=0; C(i, j) := 1 все все все все Экономный алгоритм действует аналогично алгоритму 3.9, но использует следующее правило: если v7 достижима из v, и v, соединена дугой с у„ то нет необходимости вы- яснять наличие дуги из у, в vv. В нем вершины v, выбираются так, чтобы как можно чаще встречалась такая ситуация. Для этой цели часть А алгоритма 3.9 заменяется на следующую часть А': % Ч а ст ь А' Вычисление последнего столбца в матрицах Rs и Cs; F = 1,.... s - 1 — множество свободных элементов % 1 пока F ф 0 цикл 2 . Выбрать в качестве / наибольший элемент в F, т. е.-пЭ;еР(С(й) = 1); 3 . F := F \{/}; 4 если А(/, $) = 1 то 5 R(i, s)1; C(i, s) := 1; 6 . для всех f е F и C(t, /)=1 цикл 7 R(t, s) := 0; C(t, s) := 1; F := F\{t} 8 . все 9 все все Изменения в части В' аналогичны изменениям при переходе от А к А'. Сформулиро- ванный экономный алгоритм имеет большую трудоемкость (в худшем случае), неже- ли алгоритм 3.9, который в свою очередь имеет трудоемкость в худшем случае О(л4). С другой стороны, анализ экономного алгоритма показывает, что его трудоемкость в среднем равна О(п).
210 Часть I. Обработка и визуализация графов 3.2.8. Замыкание относительно множества вершин Пусть JV, У и Z— некоторые подмножества вершин орграфа G с входом .v Замыканием У относительно Z называется такое множество вершин М(У, Z) графа G, что v, g M(Y, Z), i = 1,и, если в G найдется путь от некоторой вершины v, g У к вершине v„ в котором нет вершин из Z. Если У или Z состоят из одной вершины, то говорят о замыкании вершины или о замыкании относительно вершины. Обратным замыканием У относительно Z называется такое множество вершин N(Y, Z) графа G, что v, g N(Y, Z), i g [1 : n], если в G найдется путь от вершины v, к некоторой вершине v, g У, в котором нет вершин из Z. Алгоритм 3.10. Построение замыкания относительно Z Дано. Граф G{V, Е), заданный матрицей смежности A(G), состоящей из строк /1(1), А (2), А(п); У, Z, М— строки из нулей и единиц, соответствующие множест- вам У, Z, М(У, Z) (равенство /-го разряда единице означает, что вершина v, принадле- жит данному множеству); булевские операции над строками выполняются поразряд- но, строка, соответствующая пустому множеству, обозначается 0. Требуется. Множество М(У, Z). Метод. проц Замыкание = 1. Mo:=0;Po:=Y; 2. для к от 1 до л цикл 3. Ек := Tk& -> Мк i; % Здесь Тк есть дизъюнкция строк A(j) для всех значений j, совпадающих с номерами единичных разрядов строки Pk-i % 4. Мк := Мк 1 Ф Ек, 5. Рк := Ек & -I Z & У; все все Фактически алгоритм заканчивается, когда для некоторого г < п строка Рг не станет нулевой; в этом случае М = Мг. Из описания алгоритма следует, что при построении М(у„ 0) каждое множество Ек состоит из таких вершин v„ что кратчайший путь из v, в v, содержит к дуг. Построение множества N(Y, Z) производится с помощью этого же алгоритма, но в качестве матрицы А берется транспонированная. Для построения транзитивного замыкания графа G достаточно вычислить M{s, 0), где s •— вход G. А. Трудоемкость алгоритма равна O(nq), где q — число ячеек памяти, необходимых для запоминания п двоичных разрядов.
Глава 3 Бесконтурные графы 211 3.3. Конгруэнтное замыкание отношения эквивалентности Проблема конгруэнтного замыкания является обобщением следующей задачи экви- валентности выражений, иногда называемой проблемой унификации слов для конеч- но представленных алгебр: определить, является ли равенство t\-t2 логическим следствием множества равенств 5 = {«н = 5I2, .v2| = Л'22, -, skl =skl}, где все .v и t — вы- ражения, построенные из неинтерпретированных констант и символов операций. Указанная задача возникает в процедурах разрешения для формальных теорий, где нужно определить множества тех выражений, которые эквивалентны. Специальный случай этой задачи связан с трансляцией, где она называется проблемой общих под- выражений. 3.3.1. Задача нахождения конгруэнтного замыкания Пусть G = (И, Е) — упорядоченный орграф, т. е. орграф, в котором для любой v е К множество ПРЕЕМ(г) упорядочено. Пусть С— произвольное отношение эквива- лентности на И. Конгруэнтным замыканием С* отношения С называется минималь- ное отношение эквивалентности на И, которое содержит С и удовлетворяет следую- щему свойству для любых вершин v и w. Если v и w имеют списки преемников vb v2,..., vk и W|,..., w2,..., w/ соответственно, t=/> 1 и (v„ w,) e С* для всех i e [1 : /с], то (v, w) e С'. (Другими словами, если все пары соответствующих преемников двух вершин эквивалентны по С*, то вершинМ эквивалентны по С*.) Вычисление конгруэнтного замыкания может быть осуществлено следующей про- цедурой: пр1оц КОНГРУЭНТНОЕ_ЗАМЫКАНИЕ = 1. C:=C;i:=0; 2. ОСНОВНОЙ_ШАГ: начало 3. Занумеровать классы эквивалентности в С, начиная с 1; 4. Приписать каждой вершине v номер a(v) класса эквивалентности, содержащего V, а также сигнатуру s(v) = (a (vi), a (v2),..., a (vk)), где (v-i, V2, .... vk) = ПРЕЕМ (v); 5. Сгруппировать вершины по классам вершин, имеющих равные сигнатуры; 6. Пусть С,+1 — минимальное отношение эквивалентности на V такое, что две вершины, эквивалентные по С, или имеющие одну и ту же сигнатуру, эквивалентны по С,+ъ 7 если С,+1 = С, то С = С, 8. иначе / := i + 1; вход ОСНОВНОЙ_ШАГ все конец все
212 Часть I. Обработка и визуализация графов Корректность алгоритма очевидна, т. к. каждое выполнение основного шага приво- дит к слиянию по крайней мере двух классов, число его повторений не может пре- вышать п. Узким местом в алгоритме является выделение групп вершин, имеющих равные сигнатуры. Используя лексикографическую сортировку, это выделение мож- но осуществить за время О(т), а весь алгоритм — за время О(тп). При использова- нии хэш-таблиц этот шаг потребует O(iri), а весь алгоритм — О(тп) времени в сред- нем. Задача построения конгруэнтного замыкания отношения эквивалентности С, задан- ного на произвольном графе G = (£,£), может быть сведена следующим образом к соответствующей задаче для отношения эквивалентности С, и графа G, = (1/|,£|), в котором | ИСХОД(г) | < 2 для всех v е V(рис. 3.16). Рис. 3.16. Редукция к двум преемникам Пусть d(v)= | ИСХОД(г) | для любой v е К Определим И = Ии {х,j g [2 : и]} u {w, (v): v g V, i g [2 : J(v)]}, а также £i = {(v, V!): v g Ии vi — первый преемник v} u{(v, w2 (v)): v g И и J(v) > 2}u{(w, (v), v,): v g И, i g [2 : d(v)], v, — i-й преемник v} u{(w, (v), w/+l (v): v g И, i < <7(v)}u{(w(7(V) (v), x4v)) : v g И, J(v) >2}. Для любой v g И c d(v) >2 порядок преемников vbG, есть vh w2(v). Для вершины w,(v) с i < d(v) порядок преемников есть v„ w,+i(v). Для вершины (v) порядок пре- емников --Vt/(v), Пусть С| = Си{ (v, v) : v g И, \И}. Нетрудно видеть, что GJ является сужением С’ на И. Поэтому для вычисления С’ достаточно построить Gt и Сь вычислить G] и сужение GJ на И. Первый и третий шаги занимают О(т), а граф G| состоит из О(/и) вершин и дуг, причем первым пре- емником каждой вершины в Gi является вершина графа G.
Гпава 3. Бесконтурные графы 213 3.3.2. Быстрый алгоритм конгруэнтного замыкания Быстрый алгоритм построения конгруэнтного замыкания отношения эквивалентно- сти С, заданного на вершинах графа G, в котором d(v) < 2 для всех v е И, использует следующие структуры данных. Структура данных, называемая разбиением на классы эквивалентности, представля- ет классы эквивалентности, определяемые текущим отношением эквивалентности. Каждый класс эквивалентности имеет имя— некоторое число из [1 : |Е]]. С каждым классом эквивалентности ассоциируется список тех вершин, которые имеют хотя бы одного преемника в этом классе (при этом вершина, имеющая двух преемников в классе эквивалентности, может входить в список дважды). Над разбиением можно выполнять следующие операции: □ найти (v) — выдает имя класса эквивалентности, содержащего v; □ список (е) — выдает список вершин, имеющих преемников в классе эквивалент- ности с именем е; □ слить (еь е2) — объединяет е( и е2 в один класс эквивалентности с именем В начальный момент разбиение представляет классы эквивалентности, определяемые исходным отношением С. Структура данных, называемая таблицей сигнатур, используется для хранения вер- шин и их сигнатур. Каждая сигнатура— это либо одно целое число, либо пара целых чисел из [1 : |К|] (при этом вершины, не имеющие преемников, не содержатся в таб- лице). Над таблицей можно выполнять следующие операции: □ включить (v) — сохраняет в таблице вершину v вместе с ее сигнатурой; □ удалить (v) — удаляет v из таблицы, если она там есть; □ очередь (v) — если некоторая вершина w в таблице сигнатур имеет ту же сигнату- ру, что и v, то выдает w, иначе возвращает Л. Вначале таблица сигнатур пуста, а затем обрабатывается таким образом, чтобы лю- бая сигнатура появлялась в таблице не более одного раза. Помимо указанных структур данных алгоритм манипулирует с двумя множествами, представленными в виде списков: ОЖИДАЕМЫЕ список вершин, которые долж- ны быть включены в таблицу сигнатур, и КОМБИНИРУЕМЫЕ— список пар вер- шин, чьи классы эквивалентности должны быть объединены. Алгоритм базируется на ранее описанном алгоритме КОНГРУЭНТНОЕЗАМЫКА- НИЕ и отличается от него следующим. Вершины и их текущие сигнатуры хранятся в таблице сигнатур. В каждый момент, когда изменяется сигнатура вершины из-за из- менения класса эквивалентности одного из ее преемников, вершина заново помеща- ется в таблицу сигнатур. Если некоторая другая вершина имеет ту же сигнатуру, что и данная, происходит объединение классов эквивалентности вершин. Когда комби- нируются два класса эквивалентности, используется стратегия "изменения меньшей половины": из двух старых классов новому классу приписывается имя того, который имеет больше преемников. Таким образом, когда два класса объединяются, изменя- ются сигнатуры только вершин с предшественником в том старом классе, в котором меньше предшественников.
214 Часть I. Обработка и визуализация графов начало ОЖИДАЕМЫЕ := { v е V: d (v) > 1}; 1. пока ОЖИДАЕМЫЕ * <Z цикл 2. КОМБИНИРУЕМЫЕ := 0; 3. для всех v е ОЖИДАЕМЫЕ цикл 4. если очередь (v) = А то включить (vj 5 иначе (v, очередь (vj) -> КОМБИНИРУЕМЫЕ все; все 6. ОЖИДАЕМЫЕ := 0; 7 для всех (v, w) е КОМБИНИРУЕМЫЕ цикл 8. если найти (vj ф найти (wj то 9. если \список(найти(у)) | < \список(найти (w))| то 10 % переименование класса эквивалентности с меньшим числом предшественников приводит к тому, что меньше сигнатур должно быть заново помещено % 11. для всех и е список(найти (vj) цикл 12. удалить (и); и -> ОЖИДАЕМЫЕ; все; 13. слить(найти(ш), найтфу)) 14. иначе для всех и е список (найти (wj) цикл 15. удалить (и); и -> ОЖИДАЕМЫЕ; все; 16. слить (найти (v), найти (w)) все все все все конец Нетрудно видеть, что начальных добавлений к ОЖИДАЕМЫЕ не может быть боль- ше, чем |Р|. Каждая вершина появляется не более чем в двух списках предшественни- ков, и поэтому общий размер всех таких списков ограничен величиной 2| К). В момент слияния двух списков предшественников только вершины меньшего списка добав- ляются в ОЖИДАЕМЫЕ. Другими словами, в любой отличный от начального мо- мент добавления вершины в ОЖИДАЕМЫЕ, длина одного из списков предшествен- ников, содержащего ее, не более чем удваивается. Отсюда следует оценка IHI + 2|И|| х log2 |И| | для числа добавлений в ОЖИДАЕМЫЕ. Оценивая время работы с классами эквивалентности, получаем не более, чем |К(| - 1 операций слить, поскольку каждая из них уменьшает число классов эквивалентно- сти, а исходных классов эквивалентности не больше | К||. Количество операций спи- сок пропорционально числу операций слить и равно O(|Et|) = О(т). Число операций найти пропорционально числу добавлений к КОМБИНИРУЕМЫЕ, которое в свою очередь ограничено числом добавлений к ОЖИДАЕМЫЕ. Таким образом, О(т log т) — число операций найти. Для реализации операций над классами эквивалентности можно воспользоваться ал- горитмом реализации набора, расширив каждый класс эквивалентности циклически
Глава 3. Бесконтурные графы 215 связанным списком его предшественников и числом, специфицирующим длину этого списка. При такой реализации время операции слить есть 0(1). Время для операции список также составляет 0(1), поскольку при ее выполнении просто выдается указа- тель на список предшественников. Таким образом, О(да)— общее время выполнения операций слить и список. На выполнение О(/и log т) операций найти требуются 0(т log т) времени. Оценивая время работы операций с таблицей сигнатур, можно заметить, что число таких операций пропорционально числу добавлений в ОЖИДАЕМЫЕ, т. е. 0{т log т). Предположим, что таблица сигнатур разбита на две части: одна для тех сигнатур, которые являются отдельными числами, а другая для сигнатур, представ- ляющих собой пары чисел. Для хранения первой части можно использовать вектор размера п, и тогда каждая операция на этой части таблицы может быть выполнена за время 0(1). Вторая часть таблицы требует хранения упорядоченных пар где i g [1 : п], je [1 :|Р|]. Для хранения второй части таблицы можно использовать такие стан- дартные структуры данных, как сбалансированное бинарное дерево, п х |Е| — массив и хэш-таблицу. В первом случае получаем, что каждая операция с таблицей требует O(log т) времени, a O(w) — объем требуемой памяти. В этом случае алгоритм кон- груэнтного замыкания требует О (/«(log т)2) времени и О(т) памяти. При использо- вании п х | Е|-массива каждая операция с таблицей требует 0(1) времени, но О(тп) памяти необходимо для хранения таблицы. При такой реализации алгоритм требует O(mlogm) времении О(/«и) памяти. При использовании хэш-таблицы время каждой операции 0(1) при использовании О(/«) памяти для хранения таблицы, что приводит к временной оценке алгоритма О(/« log т) и емкостной — О(/и). Можно также использовать TRlE-структуру для поддержания упорядоченных пар. В этом случае для любого наперед заданного к необходимо O(logn/Iog к) времени для табличных операций, использующих О(кт) памяти. Таким образом, в худшем случае потребуется О(т log т log и/log к) времени и О(кт) памяти. Этот метод по- крывается как методом, основанным на использовании бинарного дерева (выбирая к = гРт), так и методом, основанным на использовании массива (выбирая к = 0(1)). Табл. 3.2 содержит сложностные оценки алгоритма конгруэнтного замыкания в зави- симости от выбранной реализации. Таблица 3.2. Оценка работы алгоритма конгруэнтного замыкания Реализация Бинарные графы Графы общего вида Время Память Время Память Сбалансированное бинарное дерево O(«(log и)2) О(/7) O(/n(log /и)2) О(/«) ЛхО(н) массив О(п log и) О(л2) О(т log т) О(тп) Хэш-таблица О(/7 log п) О(и) O(in log т) в среднем О(т) TRIE-структура О(п log)2/log к) О(кп) О(т log т log и/log к) О(кт)
216 Часть I. Обработка и визуализация графов 3.3.3. Ациклическое конгруэнтное замыкание Пусть G = (V, Е) — орграф и R — некоторое отношение эквивалентности на G. Цик- лом в G при R называется последовательность вершин v0, vi, ..., v2* = v0, в которой (v2,_2, V2/-1) G Е и (у21ч, V2,) е R для всех i е |1 : А]. Очевидно, что если G не содержит циклов при Е, то G — бесконтурный орграф. В данном разделе рассматривается задача вычисления конгруэнтного замыкания С* по заданному отношению эквивалентности С на орграфе G = (V, Е) для случая, когда G не содержит циклов при С*, т. е. является ациклическим. На рис. 3.17 приведен пример, когда G при С* содержит циклы, а при С— нет, дуги G изображены сплошными прямыми линиями, а отношение С — пунктирными. Рис. 3.17. Пример графа G и отношения эквивалентности С Имеется по крайней мере один важный случай, когда гарантируется ацикличность G при С*. Пусть G— бесконтурный орграф, и для каждой вершины v в G определен уровень v как длина самого длинного пути по G, начинающегося в v, т. е. уровень (v) = max ({0}и{урове«ь(м’) +1 : (v, w) g E}). А. Пусть G— бесконтурный граф и любые две вершины, эквивалентные по С, име- ют один и тот же уровень. Тогда G при С" является ациклическим. Б. Если G — бесконтурный граф и С — тождественное отношение, то G при С" является ациклическим. Если G при С* ациклический, то классы эквивалентности cj,..., е* отношения С* мож- но топологически упорядочить, т. е. выбрать номера таким образом, чтобы не суще- ствовало дуги из вершины класса е, к вершине класса е, при j < i. В представленном алгоритме ациклического конгруэнтного замыкания классы эквивалентности С вы- деляются в порядке, обратном топологическому упорядочению. Когда классы экви- валентности е„ ei+i,..., ek известны, перманентно фиксируется сигнатура любой вер- шины, все преемники которой появились в eh е,+1,..., ек. Алгоритм помечает класс эквивалентности (и все вершины в нем) как фиксированный, когда известны перма- нентные сигнатуры всех вершин в классе; после того как класс фиксируется, он ни- когда не сливается с другим классом.
Глава 3. Бесконтурные графы 217 проц Ациклическое конгруэнтное замыкание = 1. % Инициализация % Пусть не фиксированы все классы эквивалентности отношения С и пусть не фиксированы и не сгруппированы все вершины из V 2. пока не все вершины не зафиксированы или есть нефиксированный класс эквивалентности, имеющий фиксированными всех своих преемников (в последнем случае G при С' содержит цикл) Цикл % Основной шаг % 3. Найти нефиксированный класс эквивалентности е, все преемники каждой вершины в котором фиксированы; 4. Фиксировать все вершины вей фиксировать е, приписав ей некоторый номер 5. Пусть s — множество несгруппированных вершин, имеющих одного или более преемников, все из которых фиксированы. 6. Сгруппировать вершины s по группам вершин, имеющим равные сигнатуры. 7. Скомбинировать классы эквивалентности, соответствующие вершинам в s, имеющим равные сигнатуры. все Корректность этого алгоритма связана с тем фактом, что к концу некоторого выпол- нения тела цикла все вершины только с фиксированными преемниками сгруппиру- ются по сигнатуре и будут скомбинированы соответствующие классы эквивалентно- сти. Нет вершины, имеющей по крайней мере одного нефиксированного преемника к концу выполнения тела цикла, которая имела бы ту же сигнатуру, что и вершина без нефиксированных преемников в конце этого выполнения. Таким образом, класс эк- вивалентности на первом шаге следующего выполнения тела цикла шага является классом С* и может правильно фиксироваться. Реализация данного алгоритма, занимающая <9(/и) времени, может быть осуществле- на следующим образом. Счетчик преемников. Для каждой вершины можно поддерживать счетчик числа не- фиксированных преемников вершины. Каждый раз, когда вершина фиксируется, счетчик каждого из его предшественников уменьшается на единицу. Когда счетчик вершины становится нулем, она помещается в s. Суммарное время, необходимое для выполнения оператора 5 и поддержание счетчиков преемников, составляет О(т). Разбиение вершин. Для того чтобы группирование вершин с равными сигнатурами, выполняемое в операторе 6, могло осуществляться эффективно, можно поддерживать разбиение вершин, имеющих нефиксированных преемников. Это разбиение обладает следующим свойством. Если v и w— две вершины с преемниками vt, v2, ..., vk и W|, из,..., W/ соответственно, то они попадают в один и тот же элемент разбиения тогда и только тогда, когда для всех i либо v, или w, фиксирована, либо как v„ так и м, фикси- рованы и оба находятся в одном и том же классе эквивалентности. Вначале данное разбиение состоит из одного элемента, содержащего все вершины, имеющие нефиксированные преемники. Когда некоторый класс эквивалентности е
218 Часть I. Обработка и визуализация графов фиксируется и получает номер, происходит перестройка разбиения по следующим правилам. Для каждого значения i такого, что z-й преемник некоторой вершины со- держится в е, определяется множество q всех вершин, чьи z-e преемники находятся в е. Для каждого элемента р разбиения, чье пересечение с q не пусто, р делится на две части: р rq и р -q. Такая модификация требует времени, пропорционального коли- честву дуг, заходящих в е, если представлять разбиение в виде некоторой списочной структуры. Более того, это представление может быть реализовано таким образом, чтобы можно было за константное время определить по любой заданной вершине тот элемент разбиения, которому она принадлежит. В момент, когда должен исполниться оператор 6, две вершины в .v имеют одну и ту же структуру, если и только если они принадлежат одному и тому же элементу раз- биения. Таким образом, можно выполнять оператор 6, вычисляя р ns для каждого элемента р разбиения, содержащего по крайней мере одну вершину в s, и заменяя р в разбиении на р- s. Этот оператор требует O(|.v|) времени. Суммарное время для всех выполнений оператора 6 и всех изменений разбиения составляет O(jn). Представление классов эквивалентности. Чтобы операторы 3, 4 и 7 выполнялись быстрее, следует подходящим образом представлять классы эквивалентности. Один из подходов— использовать такую структуру данных, как набор (см. разд. 1.2.1 при- ложения 1). При этом для каждого класса эквивалентности нужно дополнительно поддерживать список входящих в него вершин и счетчик для нефиксированных. По- лучаемая тогда оценка для времени работы всего алгоритма — О(па(п, п) + т), где a(z7, и) — функция, обратная функции Аккермана. Однако несколько лучшим является подход, использующий основную идею алгорит- ма унификации Патерсона-Вегмана. Поддерживается некоторый граф G', который состоит из G и некоторых дополнительных неориентированных ребер, которые со- единяют вершины одного и того же класса эквивалентности. Для каждой группы вершин {vi, v2,..., v*}, имеющих одну и ту же сигнатуру, комбинирование классов эквивалентности в операторе 7 осуществляется добавлением к графу неориентиро- ванных ребер {vh v2},{vb v3}, ...,{vi, v*}. Поэтому общее время выполнения оператора 7 составляет O(zzz). Связные компоненты графа С, составленного из неориентирован- ных ребер, являются текущими классами эквивалентности. Нахождение классов эквивалентности для фиксации. Для осуществления всех вы- полнений оператора 3 можно использовать обход в глубину. Обход начинается с не- которой вершины V|. Если у Vi нет нефиксированных преемников, проходится неко- торое неориентированное ребро, инцидентное v(. Процесс сканирования класса экви- валентности, содержащего иь продолжается до тех пор, пока не будет найдена некоторая вершина w, в классе, который имеет некоторого нефиксированного преем- ника v2. Тогда приостанавливается сканирование класса эквивалентности, содержа- щего V!, и начинается сканирование класса эквивалентности, содержащего v2. Ука- занный обход продолжается, и строится стек частично просканированных классов эквивалентности, из которых верхний класс является активным в данный момент. Когда завершается сканирование некоторого класса эквивалентности, он удаляется из стека и выполняются операторы 4—7. Если обход проходит по неориентированному ребру, ведущему к приостановленному классу, или по ориентированной дуге, веду- щей от текущего класса либо к нему самому, либо к приостановленному классу, об- ход останавливается. В этом случае G при С* содержит цикл.
Глава 3. Бесконтурные графы 219 Когда достигается непросмотренная вершина у, ей присваивается уровень, равный числу частично просмотренных классов эквивалентности, и она помещается в стек. Хранение уровней упрощает проверку того, образует ли цикл просматриваемая дуга. В стеке вершины, имеющие один и тот же уровень, расположены последовательно. Когда обход возвращается по дуге, ведущей от меньшего к большему уровню, класс эквивалентности большего уровня полностью просканирован и все его вершины на- ходятся наверху стека. Все эти вершины удаляются из стека. 3.3.4. Уточнение алгоритма быстрого конгруэнтного замыкания Рассмотрим подробное описание алгоритма быстрого ациклического конгруэнтного замыкания, в котором каждый из элементарных шагов алгоритма (операторов про- цедуры АЦИКЛИЧЕСКОЕ_КОНГРУЭНТНОЕ_ЗАМЫКАНИЕ см. разд. 3.3.3) может быть выполнен за константное время на машине с произвольным доступом к памяти или с косвенной адресацией. проц АЦИКЛИЧЕСКОЕ_КОНГРУЭНТНОЕ_ЗАМЫКАНИЕ (V, Е, С : множество) = 1 ИНИЦИАЛИЗАЦИЯ; 2. для всех v <= V цикл 3. если УРОВЕНЬ(у) = 0 то ОБХОД (у, истина) все все все Здесь И, £ — вершины и дуги графа, а С — отношение эквивалентности, представ- ленное в виде множества классов эквивалентности. проц ИНИЦИАЛИЗАЦИЯ = 1. СТЕК := U := 0; текущий_уровень := 0; 2. текущий_класс := п + 1; РАЗБИЕНИЕ := {V}; 3. для всех / g [1 : п] цикл ф) := 0 все; 4. для всех v g V цикл 5. УРОВЕНЬ (V) := 0; d(v) := {w : (v, w) g E) все; 6. для всех e g С цикл КОМБИНИРОВАНИЕ (е) все все; Здесь U— множество неориентированных дуг, определяющих текущие классы экви- валентности. Другие переменные поясняются при описании процедур, здесь исполь- зуемых. Процедура КОМБИНИРОВАНИЕ воспринимает в качестве входа множество вершин и добавляет достаточное число дуг к U, чтобы соединить все вершины в дан- ном множестве. проц КОМБИНИРОВАНИЕ^ : множество) = 1. х;=эг. 2 для всех у g z -{х} цикл {х, у}-> U все все
220 Часть I. Обработка и визуализация графов Процедура ОБХОД осуществляет обход в глубину для нахождения классов эквива- лентности для выполнения шага 3 алгоритма. Массив УРОВЕНЬ используется сле- дующим образом. До посещения вершины v при обходе УРОВЕНБ(у) = 0. После ее посещения, но до того, как v фиксируется в некотором классе эквивалентности, УРОВЕНЬ(у)— число частично просмотренных классов, включая класс, содержа- щий v. После фиксации v в некотором классе эквивалентности УРОВЕНЬ(г) — номер этого класса. Классы нумеруются в обратном порядке, начиная с о; в некоторый мо- мент число из диапазона [1 : и] может быть либо номером уровня, либо номером класса, но не тем и другим одновременно. Процедура ОБХОД вызывается с параметром ноеый_уроеень, равным истина, если параметр v— первая вершина нового уровня, и равным ложь иначе. Переменная СТЕК содержит просмотренные, но не фиксированные вершины. Процедура ОБХОД вызывает процедуру ОШИБКА (которая не уточняется в данном разделе) в тех слу- чаях, когда она обнаруживает цикл. проц ОБХОД(у : вершина; новый_уровень : логический) = 1. если новый_уровень то 2. текущий_уровень := текущий_уровень + 1 все; 3. УРОВЕНЬ(у) := текущий_уровень\ 4. v -> СТЕК, 5. для всех таких w, что (V, и/) е Е цикл 6. если ypOBEHb(iv) = 0 то ОБХОД (w, истина) иначе 7. если УРОВЕНЬ (iv) < текущий_уровень то ОШИБКА все все все 8. для всех таких ш. что {v, и/} е U цикл 9. если ypOBEHb(w) = 0 то ОБХОДА, ложь) иначе 10. если УРОВЕНЬ(м) < текущий-уровень то ОШИБКА все все все; 11. если новый_уровень то 12. ОБРАБОТКА- НОВОГО_ КЛАССА все все Процедура ОБХОД реализует идею алгоритма унификации Патерсона-Вегмана. Из- меняя ориентацию дуг в £ и подходящим образом модифицируя процедуру ОБРАБОТКА НОВОГО КЛАССА, можно использовать обход для нахождения уни- фикаторов вместо конгруэнтных замыканий. проц ОБРАБОТКА_НОВОГО_КЛАССА = 1 КОНСТРУИРОВАНИЕ_НОВОГО_КЛАССА; 2. КОНСТРУИРОВАНИЕ-УТОЧНЕНИЙ; 3. УТОЧНЕНИЕ—РАЗБИЕНИЯ;
Глава 3. Бесконтурные графы 221 4. ГРУППИРОВКА_ПО_СИГНАТУРАМ; 5. для всех д е ГРУППЫ цикл КОМБИНИРОВАНИЕ(д) все все; Процедура КОНСТРУИРОВАНИЕНОВОГОКЛАССА, выполняющая шаг 4 алго- ритма, имеет следующий вид: проц КОНСТРУИРОВАНИЕ_НОВОГО_КЛАССА = 1. текущий_класс := текущий_класс - 1; 2. е := 0; 3. пока УРОВЕНЬ (э СТЕК) = текущий_уровень цикл 4. е<- э СТЕК; 5. УРОВЕНЬ ( э СТЕК) := текущий_класс; 6. Э СТЕК все; 7. текущий_уровень := текущий_уровень - 1; все Переменная РАЗБИЕНИЕ (см. процедуру ИНИЦИАЛИЗАЦИЯ данного раздела) со- держит нефиксированные вершины, сгруппированные по той части сигнатур, кото- рые уже зафиксированы. Ее значение состоит из односвязного списка заголовков по одному заголовку для каждой частичной сигнатуры. Заголовок указывает на двусвяз- ный список вершин с этими частичными сигнатурами. Таким образом, за констант- ное время можно добавить вершину к списку, удалить вершину из списка, найти за- головок вершины, вставить новый заголовок после данного. Процедуры КОНСТРУИРОВАНИЕУТОЧНЕНИЙ и УТОЧНЕНИЕ?АЗБИЕНИЯ изменяют РАЗБИЕНИЕ, используя новозафиксированный класс эквивалентности е. Процедура КОНСТРУИРОВАНИЕ УТОЧНЕНИЙ выполняет шаг 5 алгоритма и имеет вид. проц КОНСТРУИРОВАНИЕ_УТОЧНЕНИЙ = 1. s := ИНДЕКСЫ := 0; 2. для всех таких (v, w) е. Е, что wee цикл 3. d(v)d(v) - 1; 4. если d(v) = 0 то s —> v все; 5. Пусть / — такое, что w— /-й преемник v; 6. если ф) = 0 то / -> ИНДЕКСЫ все; 7. ф) v все все Процедура УТОЧНЕНИЕРАЗБИЕНИЯ использует функцию ПОЛОСА, которая, воспринимая на входе некоторое множество z, заменяет каждое множество р е РАЗБИЕНИЕ на р— z. Выходом функции ПОЛОСА является множество {pnz:pe РАЗБИЕНИЕ}.
222 Часть I. Обработка и визуализация графов проц УТОЧНЕНИЕ_РАЗБИЕНИЯ = 1. для всех / е ИНДЕКСЫ цикл 2. РАЗБИЕНИЕ := ПОЛОСА (ф}) и РАЗБИЕНИЕ; 3. ф) := 0 все все Процедура ГРУППИРОВКА ПО СИГНАТУРЕ выполняет шаг 6 алгоритма. Она также использует функцию ПОЛОСА. Оператор 5 процедуры ОБРАБОТКАНО- ВОГО КЛАССА осуществляет шаг 7 алгоритма. проц ГРУППИРОВКА_ПО_СИГНАТУРЕ = 1. ГРУППЫ := ПОЛОСА (S) все функ ПОЛОСА(г: множество): множество = 1. РАСЩЕПЛЕНИЕ_СПИСКА := 0; 2. для всех v е z цикл 3. Пусть р е РАЗБИЕНИЕ такое, что кер, 4. если р не расщеплено то 5. Отметить р как расщепленное; 6. р^> РАСЩЕПЛЕНИЕ_СПИСКА; 7. р' :=0; все; 8. Удалить v из р; и -> р ‘ все; 9. для всех р из РАСЩЕПЛЕНИЕ_СПИСКА цикл 10. если р = 0 то удалить р из РАЗБИЕНИЕ 11. иначе отметить р как нерасщепленное все; 12. р'^> ПОЛОСА все все Каждый элементарный шаг алгоритма занимает константное время. Общее число таких шагов— О(/и). Таким образом, он требует О(ш) времени. Емкостная его слож- ность также O(jn). 3.3.5. Случай единственной эквивалентности Пусть G — бесконтурный граф, С состоит из единственной пары вершин х и у и нуж- но вычислить С', даже если G при С* содержит циклы. Описанная ниже однопроход- ная версия алгоритма быстрого конгруэнтного замыкания решает эту задачу для слу- чая, когда степень полуисхода вершин G не превышает двух. Алгоритм обрабатывает каждую вершину один раз, приписывая номера вершинам таким образом, что две вершины эквивалентны относительно С* тогда и только тогда, когда они получают одинаковые номера. Чтобы решать, как приписывать номера,
Гпава 3. Бесконтурные графы 223 алгоритм поддерживает таблицу сигнатур (см. разд. 3.3.2). Для того чтобы избежать перенумерации вершин, алгоритм обрабатывает вершины в специальном порядке. Алгоритм состоит из двух следующих шагов. Шаг 1. Без потери общности предположим, что х имеет уровень не больший, чему. Аранжируем вершины графа G, расположив их в порядке, обратном к топологи- ческой сортировке, так, что справедливы следующие два свойства: □ у следует за х в упорядочении; □ если z — любая л акая вершина, что нет пути от х или у до z, то z следует как за х, так и за у. Шаг 2. Вершины обрабатываются в порядке, вычисленном на шаге 1. Обработка некоторой вершины v состоит из следующих действий. □ вычисляется сигнатура вершины v; □ помещается v в таблицу сигнатур. Если некоторая вершина w имеет ту же сигна- туру, что и v, приписывается v тот же номер, что и у те. Иначе, если v *у, припи- сывается вершине v некоторый ранее не приписанный номер; если v=y, припи- сывается v тот же номер, что и у Корректность алгоритма вытекает из следующе- го свойства: когда обрабатывается вершина у, ее сигнатура отсутствует в таблице сигнатур. Таким образом, алгоритм присваивает двум вершинам один и тот номер в том и только в том случае, если они имеют одну и ту же сигнатуру или они являются х и у. Это означает, что нумерация, осуществляемая алгоритмом, соответствует С’ и что не возникает необходимость в перенумерации. Время, необходимое алгоритму, определяется временем, затрачиваемым на доступ к таблице сигнатур; метод требует О(т) времени плюс О(т) табличных операций. Если используется TRIE-структура для представления таблицы, сложность алгоритма в худшем случае составляет G(wlog и/log к) времени и O(km) памяти. Если же ис- пользуется хэш-таблица, то алгоритм требует О(т) времени в среднем и О(и) памяти в худшем. 3.3.6. Симметричное конгруэнтное замыкание Пусть G = (l',E)— некоторый орграф и пусть С— некоторое отношение эквива- лентности на И. Симметричным конгруэнтным замыканием С' отношения С является минимальное отношение эквивалентности на И, содержащее С и удовлетворяющее следующему свойству: если v и w— вершины с преемниками vb v2,..., v* и wb w2,..., соответственно, k = l> 1, и существует перестановка л на [1 : А] такая, что (vb и)е С для всех i е [1 : А], то (у, и) е С'. Нахождение симметричного конгруэнтного замыкания необходимо для решения задачи эквивалентности выражений (см. разд. 3.3.8), когда все операции коммутативны. Задача нахождения симметрич- ного конгруэнтного замыкания является также обобщением задачи проверки изо- морфизма корневых деревьев. Алгоритмы, описанные в разд. 3.3 2 и 3.3.3, могут быть модифицированы для нахож- дения симметричного конгруэнтного замыкания с теми же требованиями к ресурсам.
224 Часть I. Обработка и визуализация графов Основная идея данной модификации связана с сортировкой преемников вершины, для которой вычисляется сигнатура, по номерам их классов эквивалентности. В алго- ритме ациклического конгруэнтного замыкания такая сортировка неявно имеет ме- сто. Единственная трудность этого подхода связана с тем, что переход от графов об- щего вида к графам со степенями исхода, не превышающими двух, не сохраняет симметричных транзитивных замыканий; однако в большинстве приложений графы имеют степени исхода, не превышающие двух. Далее, легко обобщить алгоритмы таким образом, чтобы разрешить некоторым вершинам иметь упорядоченные множе- ства преемников, а другим — неупорядоченные. 3.3.7. Унификация Пусть G = (V, Е) — некоторый орграф и С — некоторое отношение эквивалентности на V. Унификатором С" отношения С является минимальное отношение эквивалент- ности на V, содержащее С и удовлетворяющее следующим двум свойствам: П если (v, w) е С", то d(y) = d(w) или хотя бы одно из d(y), и d(w) равно нулю; П если v и w— вершины с преемниками vb v2> •••> vk и wb w2, wt соответственно, k = I> 1 и (v, w) e C“, to (v„ w,) e С" для всех i e [1 : k\. Задача вычисления унификаторов дуальна по ориентации к задаче конгруэнтного замыкания; она возникает при проверке эквивалентности конечных автоматов и при нахождении наибольшей подстановки, делающей два выражения равными Хопкрофт и Карп предложили О(т ос(ш, и)) — алгоритм для решения общей задачи с использо- ванием наборов для хранения объединяемых множеств, а Патерсон и Вегман — О(т) — алгоритм для случая, когда G при С" является ациклическим. Некоторые из идей Патерсона и Вегмана использованы в алгоритме ациклического конгруэнтного замыкания, описанном в разд. 3.3.3. Задача унификации в определенном смысле яв- ляется более простой, чем задача конгруэнтного замыкания, поскольку в ней две вершины должны быть эквивалентны, если эквивалентна некоторая пара соответст- вующих предшественников, в то время как при конгруэнтном замыкании две верши- ны должны быть эквивалентны, если эквивалентны все пары соответствующих пре- емников. 3.3.8. Проверка эквивалентности выражений Наиболее важным приложением конгруэнтного замыкания является решение сле- дующей задачи эквивалентности выражений: определить, является ли равенство t\ = t2 логическим следствием множества равенств 5= {$ц-.$12, ^2i = 522, ^*1 = ^2}, где все 5 и t являются выражениями, построенными из неинтерпретированных кон- стант и символов операций. Эта задача является центральной при верификации про- грамм и решается при неявном использовании конгруэнтного замыкания. Идея состоит в следующем. Конструируется граф G, содержащий по одной вершине для каждой переменной, каждого символа операции и каждого подвыражения, встре- чающемуся в равенствах. Переменной х соответствует вершина v(x) со степенью ис- хода 0; каждому символу операции ® соответствует вершина И(®) со степенью исхо-
Глава 3. Бесконтурные графы 225 да 0, каждому выражению г = ® (гь г) соответствует вершина v(r) с преемниками v (0), v(ti), v (г;) (в указанном порядке). Конструирование данного графа требует времени, линейного от суммарного размера множества равенств, если все перемен- ные и символы операций закодированы разумно небольшими числами. В качестве отношения эквивалентности С рассматривается наименьшее отношение эквивалентности, содержащее (v(i'n), v(i12)) для всех / е [1 : А]. Затем вычисляется конгруэнтное замыкание С* для G при С. Равенство tt = t2 логически следует из £= {$! | - S|2, ^21 = 522> slcl = Ski) тогда и только тогда, когда v (/,) и v (Z2) эквивалентны относительно С*. Таким обра- зом, можно решить задачу эквивалентности выражений за время, линейное относи- тельно размера множества равенств, плюс время, необходимое для вычисления един- ственного конгруэнтного замыкания. Алгоритм легко обобщить на решение задачи определения того, какие из равенств некоторого множества 7’= {^11 = ^12, Ъ| = ..., Z,i — zf2} логически следуют из некоторого множества S = {S| I = S|2, s2l = ^22> •••» = - Граф G, изображающий множество выражений, является бесконтурным, но G при С’ не обязан быть ациклическим. Однако, если задача, которую нужно решить, состоит в идентификации идентичных подвыражений, тогда 5— пустое множество, и G при С* является ациклическим. Алгоритм построения ациклического конгруэнтного за- мыкания может быть использован для нахождения общих подвыражений за линейное время. Как описано выше, алгоритм легко модифицируется, позволяя коммутативность опе- раций. Если ® коммутативна, граф G конструируется таким образом, что некоторое выражение ® (гь г2) представляется вершиной v(® (гь г2)) с двумя упорядоченными преемниками, v(®) и новой вершиной х; х имеет двух неупорядоченных преемников, v(r,) и v(r2). Ассоциативность более сложна для обработки, чем коммутативность. Для заданного множества равенств 5= {5ц = Л|2, s2i = s22, s*i = sk2} выражений, построенных из констант и единственной бинарной ассоциативной операцией, проблема определе- ния, является ли некоторое другое равенство = t2 следствием из S, называется про- блемой унификации слов для полугрупп; она неразрешима. Даже если S зафиксиро- вано и только Z, = h может изменяться, она остается неразрешимой. Если операция — коммутативна, получаем проблему унификации слов для коммутативных полугрупп, которая является NP-SPACE-полной. Даже следующая проблема является NP- полной: по заданному множеству выражений Е, построенному из констант и единст- венной коммутативной и ассоциативной операции, определить наименьшее число операций, необходимых для вычисления всех выражений из Е. 3.3.9. Проверка свойства соединения без потерь Проблема эквивалентности выражений в различных формах возникает при изучении реляционных баз данных. Одним из таких приложений является проверка свойства 8 Зак 202
22G Часть I. Обработка и визуализация графов "соединения без потерь", которая может быть выполнена за время О(п2 log») сле- дующим алгоритмом Ахо — Беери — Ульмана. Алгоритм воспринимает в качестве входа некоторое множество Л={1,2,/?} атри- бутов; некоторый набор Rh R2,R,„ реляционных схем, каждая из которых есть не- пустое подмножество А, и набор rh г2,..., г/ правил функциональной зависимости, каждое г, из которых имеет вид А',-> У„ где Л, и У,— непустые подмножества А. Алгоритм начинает с построения m х Л-матрицы Т вида: fa,, если / в R,, 1оу, иначе, где все а и b — различные символы. Алгоритм в процессе своей работы объявляет символы Т(у j) эквивалентными, ис- пользуя следующее правило: (£>) Если Хр—>Ур является правилом функциональной зависимости и i,j—- две строки Ттакие, что T(i, д') эквивалентен T(j, д) для всех де.Хр, то Tfi, г) и T(J, г) эк- вивалентны для всех г е Y. Алгоритм использует это правило до тех пор, пока оно применимо; тем самым он вычисляет минимальное отношение эквивалентности на символах из Т, которое удовлетворяет (£)) и может быть названо замыканием зависимости D* для Т. А. Реляционная схема базы данных, определенная через R\, R2, .., R,„ вместе с функ- циональными зависимостями rt, г2,..., Г/, обладает свойством соединения без потерь тогда и только тогда, когда некоторая строка Т имеет своими символами эквива- лентные символам а по D‘. (Следует заметить, что (£>) объявляет символы в неко- тором столбце Т эквивалентными’, таким образом каждый by в Т имеет единствен- ный а, а именно а,, с которым он может стать эквивалентным.) Можно трансформировать задачу вычисления замыкания зависимости в задачу вы- числения конгруэнтного замыкания на некотором подходящем графе Во-первых, удобно применить прием, предложенный Ульманом, для преобразования правил функциональной зависимости к виду, в котором каждое правило имеет только один атрибут в своей правой части. Если X, —> Y, является правилом функциональной зави- симости, в котором Y, содержит, как минимум, два атрибута, вводится новый атрибут х и заменяется X, —> У, на правило X, х и множество правил {х —>у :у е У,}. При- менение указанной конструкции ко всем исходным правилам увеличивает число ат- рибутов не более чем на /, и увеличивает общую длину не более чем на 2/. Более то- го, если D* является замыканием зависимости таблицы Т, соответствующей исходной схеме, D\ — таблицы 7\, соответствующей новой схеме, два символа Т эквивалентны по D* тогда и только тогда, когда они эквивалентны по D\. Пусть теперь каждое правило функциональной зависимости имеет вид X, —> У„ где Y,— единственный атрибут. Граф G = (P,E) конструируется следующим образом. Множество вершин V состоит из символов Т и одного дополнительного символа С,р для каждой пары, состоящей из строки i таблицы Т и правила зависимости Хр —> Yp, и одного дополнительного символа fp для каждого правила зависимости Хр —> Yp. Для
Глава 3. Бесконтурные графы 227 каждой вершины с,р множество дуг Е содержит дуги (с,р, fp), (cip, (с,р, T(J,j2)), , {с,р, T(j, jr}), где Xp= {j},j2, jr} c j, <J2 < ...<jr . Отношение эквива- лентности С на И определяет эквивалентными cip и Т{1, ур) для i е [1 : т] и р е [1 : Легко видеть, что если С — конгруэнтное замыкание С на G, то D* является сужени- ем С’ на символы из Т. Таким образом, можно применять быстрый алгоритм конгруэнтного замыкания для вычисления замыканий зависимостей. Граф G состоит из не более чем ди(/? + 2/) вершин и не более чем m(t + 2/) дуг, где t — суммарная длина всех правил функцио- нальной зависимости. (Указанная оценка учитывает разрастание, вызванное преобра- зованием правил зависимости, в вид, при котором все правые части правил имеют единственный атрибут.) Следовательно, G имеет размер О(и2), где и— общая дли- на реляционных схем и правил зависимости. Поэтому алгоритму требуется O(«2(log п)2 /log к) времени и О(кп2) памяти для вычисления замыкания зависимостей, где А— некоторый произвольный параметр. Следует заметить, что указанные оценки в практических применениях представляются весьма пессимистичными. 3.4. Нахождение ближайших предков Рассматривается следующая проблема. Задан набор корневых деревьев. Требуется ответить на запросы вида: "Кто является ближайшим общим предком вершин х и у?". Имеется несколько вариантов постановки данной проблемы в зависимости от того, известны ли все запросы заранее и насколько существенно перестраиваются деревья в ходе запросов. 3.4.1. Постановка проблемы Пусть корневое дерево Т определяется как множество вершин V, корень г е V и ото- бражение р(у): V \ {/ } —> К, такого, что для каждой вершины v существует целое />0, для которого р (у) = г, где р'(у) определяется индуктивно по следующим прави- лам: (v) = v, р'' ‘(v) = р(р'(у)). Напомним, что для любой v е К\ {г} вершина р(у) является отцом v, a v— сыном р(у). Дуги Т — это пары вершин (у,р(у)) для всех v е VI {/}; мы их будем обозначать как v -> р(у). Если р‘(у) = w для некоторого / > 0, то v является потомком мл, a w — предком V. Две вершины не связаны, если ни одна из них не является предком другой. Путем по Т является последовательность вершин V, р(у\ ..., pk (v); длина этого пути равна к. Глубина вершины v — это длина пути от v до г; высота вершины v — это длина длин- нейшего пути от листа до v. Глубина (и высота) дерева Т — это длина длиннейшего пути по Т. = п обозначает количество вершин в Т, т. е. п = |Е] = |7] . Ближайшим общим предком (nearest common ancester) двух вершин х и у (обозначает ся пса(х, у)), называется вершина наибольшей глубины, которая является предком какх, так иу. Во многих приложениях рассматривается следующая проблема. Для заданного набо- ра корневых деревьев требуется ответить на запросы вида: "Кто является ближайшим
228 Часть I. Обработка и визуализация графов общим предком вершин х и у?". Имеется несколько уточнений общей постановки данной проблемы в зависимости от того, известны ли все запросы заранее и насколь- ко существенно пересзраиваются деревья в ходе запросов. Обычно рассматриваются следующие пять вариантов данной проблемы, перечисленные в порядке от наименее динамичной (наипростейшей) к наиболее динамичной (наитруднейшей): 1. Автономная задача. Набор деревьев статический, и вся последовательность за- просов специфицирована заранее. 2. Задача со статическими деревьями. Набор деревьев статический, но запросы об- рабатываются оперативно. Это означает, что ответ на запрос должен быть получен до того, как станет известен следующий запрос 3. Задача с соединением корней. Запросы обрабатываются оперативно. Наряду с во- просами оперативно отрабатываются команды вида соединить{х,у), где х и у — корни деревьев. Эффект от команды соедииить{х, у) состоит в объединении де- ревьев, содержащих х и у, в результате которого х становится отцом у. 4. Задача с соединением. Запросы обрабатываются оперативно. Наряду с вопросами оперативно отрабатываются команды соединить{х, у), в которых у (но не обяза- тельно х) является корнем. 5. Задача с соединением и разрезанием. Запросы обрабатываются оперативно. Наря- ду с вопросами оперативно отрабатываются команды двух видов: соединить (х,у), где у, но не обязательно х, является корнем, и разрезать{х), где х не является кор- нем. Действие команды разрезать{х) состоит в разрезании дуги, соединяющей х и его отца, в результате которого расщепляется дерево, содержащее х, на два дерева: одно из всех потомков вершины х, а другое из всех вершин, не являющихся по- томками х. 3.4.2. Общий вид быстрого алгоритма для статических деревьев В данном разделе и в разд. 3.4.3, 3.4.4 описывается алгоритм для статических деревь- ев {см. разд. 3.4.1, задача 2), который требует О{п) памяти, О{п) времени для предва- рительной обработки и 0(1) времени для ответа на запрос. Указанные оценки являются наилучшими по порядку из возможных. Имеется и"-1 различных корневых деревьев с п помеченными вершинами. Это означает, что Q(h log п) битов, или П(н) ячеек, необходимо для хранения и-вершинного дерева в РАМ. Только чтение в таком дереве требует Q(h) времени, а ответ на запрос требу- ет Q(l) времени. Пусть Т— полное бинарное дерево. Тогда ответ на запрос о наибольшем общем предке может быть получен за 0(1) времени следующим образом. Пусть вершины Т занумерованы в симметричном порядке (рис. 3.18), и пусть sym(v) обозначает номер вершины v, a sym"'(/) — вершину, номер которой равен i. Для лю- бого h вершины, имеющие высоту Л, получают номера 2* 3 х 2*, 5 х 2",... в порядке их расположения слева направо.
Глава 3. Бесконтурные графы 229 Справедливы следующие свойства симметричной нумерации: А. Высота вершины v, обозначаемая через fi(v), является наибольшим таким целым числом h, что 21 делит sym(v). Б. Потомками вершины v являются все те вершины, номера которых принадлежат диапазону (sym(v) - 2Л<,) + 1, sym(v) + 2/,{v) — 1 ]. В. Если v — вершина и И — высота, такие, что h > h(v), то предок v высоты h имеет номер 2Л' ’L 5ут(у)/2Л 1J + 2h. Г. Если vuw — две несвязные вершины, то высота ближайшего общего предка рав- на Llg (sym(v) ffi sym(w))J, где i Ф j — число, двоичное представление которого полу- чается покомпонентным исключенным или из двоичных представлений i и j. Свойства 3.4.2, Б и 3.4.2, Г позволяют по известным номерам и высотам всех вершин дерева и его высоте d определять за время 0(1) для любых заданных вершин v и w глубину пса (v, w) (задача глубины пса) по следующему правилу: □ если v— предок w (т. е. если sym(w) е [sym(v) — 2/,(v) + 1, sym(v)+ 2Л<1) — 1]), то глубина вершины nca(v, w) равна d-h(y)\ □ если w и v — две не связанные вершины, то глубина вершины nca(v, w) равна d — Llg(sym(v) ® sym(w))J. Свойства 3.4.2, А и 3.4.2, В позволяют по известным номерам и высотам всех вершин дерева и глубине d дерева определять за время 0(1) для любой вершины v глубины d\ и любой глубины rf, - d\ того предка вершины v, глубина которого равна d2 (задача глубины), по следующему правилу: Пусть h = d-d2, тогда вершина syin-l(2/,,lLsym(v)/2MI J 2h) является предком вер- шины v глубины d2. Алгоритм, вычисляющий за время 0(1) ближайшего общего предка заданных вершин v и w, объединяет эти два правила: функ NCA (i/,w: вершины) = 1. Вычислить в do глубину вершины nca(v, w); , 2 возврат предка вершины v, имеющего глубину do
230 Часть I. Обработка и визуализация графов Временная сложность 0(1) алгоритма связана с возможностью выполнения умноже- ния, деления, возведения в квадрат, нахождения логарифма по основанию два и ре- зультата покомпонентного исключенного "или" за время 0(1). Если указанные опе- рации не являются машинными командами, можно за время О(и) построить таблицы операций, которые позволят за время 0(1) выполнять указанные операции, используя (возможно повторные) поиски по таблицам. Задача нахождения ближайшего общего предка на произвольном дереве Т может быть сведена к задаче нахождения пса на некотором поддереве полного бинарного дерева умеренного размера, которая может быть решена описанной функцией NCA Сведение осуществляется последовательностью шагов, которая включает решение задач глубины и глубины пса для двух фиктивных деревьев: сжатого дерева С и сба- лансированного бинарного дерева В. Дерево С имеет то же множество вершин, что и Г; В содержит все вершины Т, а также, возможно, некоторые фиктивные вершины. Для упрощения получения решения задач глубины для В и С, оба из этих деревьев разбиваются на слои. Построение В и С осуществляется на предварительном шаге, который требует О(р) времени. Алгоритм вычисления nca7(v, w) состоит из двух по- следовательных шагов: Шаг 1. Вычислить ncac(v, w) следующим образом: П Вычислить псад(г, vv), применяя алгоритмы решения задач глубины пса и глубины кВ. П По заданному псаДу, w) взять значение пса< (v, w). Шаг 2. Взять глубину nca6(v, w) в С. Применяя к С алгоритм решения задачи глуби- ны, вычислить пса7 (v, и>). Каждый из этих шагов требует 0(1) времени. Подробное рассмотрение данного ме- тода см. в разд. 3.4.3 и 3.4.4 3.4.3. Сжатое дерево Пусть Т — произвольное и-дерево с корнем г. Сжатое дерево С, представляющее Т. определяется следующим образом. Для каждой вершины v дерева Т пусть size(v) оп- ределяет размер вершины v— число потомков v (включая саму v) в Т. Дуга v —> Рг(у) называется легкой, если 2size(v) < size-/- (p/(v)), и тяжелой — в противном случае. Поскольку размер вершины всегда на единицу больше суммы размеров ее сыновей, не больше одной тяжелой дуги может исходить из вершины. Таким образом, тяжелые дуги разбивают вершины Т на набор тяжелых путей (вершина без заходящей и исхо- дящей тяжелых дуг образует одновершинный тяжелый путь). На рис. 3.19 приводит- ся пример дерева с разделением на легкие и тяжелые дуги и размерами вершин, ука- занными рядом с соответствующими вершинами. Вершина, которая имеет наименьшую глубину, обозначается — apex тяжелого пути, apex(v) для некоторой вершины v— apex тяжелого пути, содержащего v, а hpsize(v) — количество потомков v, принадлежащих этому тяжелому пути. Сжатое дерево С определяется множеством дуг {v —> apex(pz(v)) : v— любая вершина дерева Т, отличная от его корня}. Для дерева Т (см. рис. 3.19) сжатое дерево Т будет иметь вид, изображенный на рис. 3.20.
Глава 3. Бесконтурные графы 231 Рис. 3.19. Разделение дуг дерева на легкие и тяжелые Рис. 3.20. Сжатое дерево
232 Часть I. Обработка и визуализация графов За время О(п) можно вычислить следующую информацию для каждой вершины v; р7(у), р<{у), apex(v), hpsize(v), c/<(v) (глубина v в Q и size<~(y). Следует заметить, что можно использовать apex для проверки за время (9(1), находятся ли две вершины на одном и том же тяжелом пути по Т. Для вычисления ncay (v, w) вначале вычисля- ется nca< (v, w) при использовании сбалансированного дерева В (см. разд. 3.4.4). За- тем выполняются нижеперечисленные действия, составляющие шаг 2 алгоритма для вычисления ncay(v, w) (см. разд. 3.4.2): П Пусть w = ncar(v, w) (либо u = v~w, либо и является apex тяжелого пути, содер- жащего ncaz(v, w)). Если и = у или и — w, то возвратить и в качестве nca7(v, w). Иначе вычисляется ффи). П Вычисляется тот предок у' вершины v в С, глубина которого равна d((u) + 1. Если apex(v) = г/ (г/ и v лежат на одном и том же тяжелом пути), устанавливается v" = v; иначе v" = p/(v')- □ Вычисляется тот предок w' вершины м в С, глубина которого равна d((u) + 1. Ес- ли apex(w') = и (и и w' лежат на одном и том же тяжелом пути), то пусть w" = w1', иначе пусть w" = p-^w1). П Возвратить в качестве nca7(v, w) ту из вершин у" или w", которая имеет большее значение hpsize. □ Например, для дерева Т, изображенного на рис. 3.19, имеем пса( (и, о) = а (см. рис. 3.15), п' = п, п"= и, о' = с, о" = о и пса,(и, о) = а. Шаг 2 требует (9(1) времени плюс время, необходимое для решения не более чем двух задач нахождения глубины на С. Для их решения необходима некоторая пред- варительная обработка, которая использует следующие свойства: А. Если v является apex, то sizef-(y) = size7(y); если v не является apex, то sizec(y) = 1. Б. Всякая дугах —>Р((у) дерева С удовлетворяет неравенству 2size( (v) < size(-(p6(y)). В. Глубина С не превышает Llg п]. Пусть С разбит на три слоя. Ранг вершины v (обозначение rank(v)) определяется как L lg(sizef (v))J. Третий слой состоит из всех тех вершин, ранг которых не меньше Llg(2)nJ; второй — из всех тех вершин, ранг которых лежит в диапазоне от Llg13’«J до Llg(2)nJ - 1; первый слой — это все вершины, у которых ранг меньше Llg(3)nJ (исполь- зуется следующее обозначение: для любого неотрицательного i и функции f опреде- ляется /'\х) по правилу/01^) = х,/' 0(х) =/(/*')(х))) (рис. 3.21). Алгоритм предварительной обработки использует также следующие свойства: Г.Для любого ранга i число вершин ранга i не превышает п/2'. Д. Третий слой содержит не более 0(n/log п) вершин. Второй слой содержит не бо- лее (9(n/log(2)n) вершин Каждая связная компонента первого слоя является поддере- вом С, содержащим не более lg(2)n вершин С каждой вершиной v в слое i (i = 1, 2, 3) хранится вершина a(v) такая, что a(v) явля- ется наиболее мелким предком v в С, находящимся в слое i. Каждый слой представ-
Глава 3. Бесконтурные графы 233 ляется таким образом, что можно за время 0(1) по любой заданной вершине v в слое / и любой глубине d е [Jr(«(v)): t/(-(v)] находить предка вершины v, имеющего глубину d. Тогда за время 0(1) можно находить по заданным вершине v и глубине d такого предка v в С, глубина которого равна d, повторяя до получения результата следую- щее действие если d е [c4(«(v)): df (v)], то найти и выдать в качестве результата того предка v, глубина которого равна <7; в противном случае заменить v на рс(а(уУ). Рис. 3.21. Слои сжатого дерева Первый слой Второй слой Третий слой Представление второго и третьего слоев довольно простое. С каждой вершиной v слоя i, i = 2, 3, хранится массив всех ее предков в слое i, индексированных по глуби- не. Тогда задачу нахождения предка заданной глубины внутри второго или третьего слоя можно решать за время 0(1), обращаясь к таблице, составленной из массивов предков вершин. При этом по свойству 3.4.3, Д общий объем всех массивов третьего слоя составляет O((n/log «)log ri) = О(л), т. к. любая вершина имеет O(log ri) предков в С, а общий объем второго слоя — <X(«/log(2) и)log w) = O(ri), поскольку любая верши- на имеет O(log(2> ri) предков второго слоя в С. Таким образом, можно разбить верши- ны по слоям, вычислить a(v) для всех вершин и сконструировать все массивы для второго и третьего слоев за время О(п). Первый слой имеет очень небольшие связные компоненты, но содержит большинст- во вершин в С и представляется другим образом, чем второй и третий слои. Пусть V— некоторая вершина первого слоя. Обозначим через £>o(V) поддерево дерева С с корнем o(v); это — связная компонента первого слоя, содержащая v. Da^ содержит не более 1g 2)и вершин и имеет глубину не более lg<3)«. Пусть d— глубина Da,v^. Верши- ны дерева D встраиваются в полное бинарное дерево Еам глубины d Г 1g'3 и"| таким образом, что вершина глубины i в имеет глубину i Гlg(3)nl в £о(,.), и если v— вер- шина глубины i в и /' е [0 : /], то предок v в DO[V), глубина которого равна яв- ляется предком v в £O(V), глубина которого равна 7[lg(3)«l (рис. 3.22). Тогда предок вершины v в С, глубина которого есть d (v находится в первом слое и d > t/(-(o(v))), вычисляется по формуле sym'lo(V)(2;'+l Lsym(v)/2/,+"J + 2*), где h = (d((a(v)) — d) Flg<3)«l, sym(v)— номер вершины v в симметричном порядке, соответствующий ее позиции в и либо sym-la(V)(7) является вершиной в £o(,,j с номером /, если она является вершиной в DO(V), либо значение synT'^i) неопределено — в противном случае. Ука- занный метод позволяет решать задачу нахождения предка по указанной глубине впервом слое за время 0(1), если sym и sym*1^,.; предварительно вычислены. Поскольку деревья £иМ достаточно велики по размеру, они должны представляться неявно Для представления деревьев £я(1.) хранятся два числа— sym(v) и pre(v) —
234 Часть I. Обработка и визуализация графов с каждой вершиной v первого слоя, и два массива— рге-|О(,,) и inverseo(1.)— с каждой вершиной а(у) первого слоя. Значения pre, pre-1 и inverse определяются по следую- щим правилам. Вершины каждого дерева нумеруются в предпорядке от 1 до |£„м|. Если v является вершиной в DaM, pre(v) — это номер v и pre-la(v)(pre(v)) = v. Яс- но, что О(п) — суммарный размер массивов pre-la(v) всех вершин а(у) в первом слое. Для каждого i е [1 : |£o(v>l], inverseo(1,)(z)— предпорядковый номер вершины в Do(V), номер которой в симметричном упорядочении £o(v) равен z; inverse^,,//) = О, если не находится в Da^ та вершина из £оМ, номер которой в симметричном упорядочении равен i. Нетрудно видеть, что inverse^ содержит |£>a(v)| ненулевых элементов и тре- бует О(| £o(v)| 1g |£O(V)D = 20((l8(3)n)2)lg(3) = O(log ri) битов для своего хранения. Таким об- разом, общее число ненулевых элементов всех массивов inverse^) составляет О(и), и каждый массив inverseo(v) может размещаться в одной ячейке памяти. Рис. 3.22. Встраивание в полное бинарное дерево Имея sym(v) для каждой вершины v в первом слое и pre 'О(„) и inverseo(1,) для каждой вершины o(v) в первом слое, можно решать задачу глубины в первом слое за 0(1)
Гпава 3. Бесконтурные графы 235 времени, поскольку sym z) = рге-|оМ (inverse,,(1)(z)), если i— номер в симметриче- ской нумерации Еи^ вершины в D„(v). Нетрудно построить массивы pre-l„(,,) за время 0(л). Построение номеров sym и массивов inverseO(r) может быть осуществлено в процессе обхода в предпорядке каждого дерева первого слоя следующим образом. Пусть Oof,,) является деревом первого слоя высоты Л, которое встроено в полное би- нарное дерево Eu(v). Вначале inverse,,;,., получает значение нуль. Затем выполняется ТРАВЕРС(ф-), ЛГ1Е(3)и1, 1), где процедура ТРАВЕРС определена следующим об- разом: процТРАВЕРС(и, А, /) = 1. % v— некоторая вершина в Оа«, А — высота v в ЕаМ, z— номер в симметричном упорядочении потомка v в Еам. имеющего наименьший номер %; 2. J := 2ЛГ//2кП; 3. % j — номер v в симметричном упорядочении Еам % sym(v) = / inversea(v) := pre(v); 4 к := i; 5. для всех сыновей и/ вершины v цикл 6. ТРАВЕРС (и/, А - Г 1д(3)л1, к), 7 fa •= к + + 1 все все 3.4.4. Сбалансированное бинарное дерево Сбалансированное бинарное дерево В используется для представления сжатого дере- ва С и содержит все вершины С, называемые зелеными вершинами, а также некото- рое множество дополнительных вершин, называемых красными. Для каждого семей- ства в С, состоящего из некоторого отца v и множества сыновей W, В содержит под- дерево с корнем v, листьями IV и другими вершинами, являющимися красными. Каждая вершина v имеет указатель на своего ближайшего зеленого предка green(v). Ближайшие общие предки в В и С связаны соотношением nca({v, w) = green(nca;((v, w)), если v и w— вершины в С. Таким образом, если под- задача может быть решена на В, то она может быть решена на С с 0(1) дополнитель- ным временем. Для описания процесса построения В рассмотрим одно из семейств в С, состоящее из отца v и множества его сыновей W, \ W\ >3. Чтобы привести его к бинарному виду, выполняется БИНАР(г, w), где процБИНАР(и: вершина; W: множество вершин) = к 1. Пусть W= {W1, ..., W/,} и s = ^Tsize^w,); >=i к 2. Пусть j — такой минимальный индекс, что y"sizec (и/,) s/2; i=i
236 Часть I. Обработка и визуализация графов 3. если/' = кто j := к- 1 все; 4. если / = 1 то 5. Подсоединить ил, в качестве левого сына v 6. иначе Пусть Xi — новая красная вершина; 7. Подсоединить xi в качестве левого сына и; 8 БИНАР (xi,{ и/1, .... и/,}) все; 9. если j = к - 1 то 10. Подсоединить wk в качестве правого сына v 11. иначе Пусть х2 — новая красная вершина; 12. Подсоединить х2 в качестве правого сына V, 13. БИНАР (х2,{ и>1, ..., iv*}) все все На рис. 3.23 изображено сбалансированное бинарное дерево, соответствующее сжа- тому дереву (см. рис. 3.20), в котором красные вершины представлены точками. Рис. 3.23. Сбалансированное бинарное дерево Данный алгоритм может быть реализован с временной сложностью O(|JT|). Идея та- кой реализации состоит в конструировании массива размера к, j-й элемент которого к содержит ^sizec(wy). Тогда можно найти подходящий индекс у за время i=i
Гпава 3. Бесконтурные графы 237 O(log(min{/, k-j})), используя некоторый вариант бинарного поиска одновременно от обоих концов массива. Тот же самый массив может использоваться для всех ре- курсивных вызовов. Время работы алгоритма /(А) определяется рекурсивным соот- ношением / (Ar) = max {/(/) + t(k-j) + O(log(min {/, k-j}) + 1)}, O<j<k которое имеет решением t(k) = O(k~). Для конструирования В каждое семейство в С обрабатывается указанным методом. Поскольку В содержит не более 2и - 1 вершин, общее время конструирования В есть 0(и) Пусть size’ft(v) для любой вершины v в В обозначает количество зеленых потомков v в В. Справедливы следующие свойства дерева В. А. Для любой зеленой вершины v size/((v) = sizef (v). Б. Если v — такая вершина, что р4ц(у) определено, то 2-size«(v) < sizc/;(p\(v)). В. Дерево В имеет глубину 0(Jog ri). Задача пса на В решается путем решения задач глубины пса и глубины на В. Чтобы решить задачу глубины пса на В, дерево В встраивается в полное бинарное дерево В' и используется прямой метод вычисления, с.м. разд. 3.4.2; для каждой вершины в В необходимо знать только ее номер в симметричном упорядочении и высоту (как не- которой вершины в В). Нумерацию вершин В осуществляет выполнение HOMEP(r, h, 2Л), где г — корень В, h — высота В, а процедура НОМЕР определена следующим образом: проц HOMEP(v, h, i) = 1. % v — некоторая вершина в В, h — высота вершины 1/вВ'и i— номер в симметричном упорядочении вершины v в В % 2. Приписать номер i и высоту h вершине v, 3. если v имеет левого сына и/, то 4 НОМЕР (W1 Л-1,/-2м) все; 5. если v имеет правого сына wto 6. HOMEP(w2, /7-1,/+2м) все все Это вычисление требует О(п) времени. Когда вершины В занумерованы, задача глу- бины пса может решаться за время 0(1). Решение проблемы глубины на В означает ее решение на С. Для каждой вершины v в В определяется rank^v) = Llg(sizefi(v))J. Дерево В делится на три слоя следующим образом: третий слой состоит из всех вершин, ранг которых не меньше Llg(2)nJ, вто- рой слой состоит из всех вершин, ранг которых принадлежит диапазону от Llg(3)«J до Llg2)nJ — 1 (включая границы), а первый слой— все оставшиеся вершины. Свойство
238 Часть I. Обработка и визуализация графов 3.4.3, Д справедливо как для слоев в В, так и для слоев в С, но с тем отличием, что константы увеличены в четыре раза, поскольку свойство 3.4.3, А, справедливое для В, является более слабым, чем аналогичное свойство 3.4.3, Б. Для дерева В слои представляются точно так же, как и слои С, и задача глубины решается аналогичным способом. Можно, однако, несколько упростить представление первого слоя, по- скольку В— бинарное дерево; в частности, нет необходимости приводить к бинар- ному виду деревья первого слоя. 3.4.5. Быстрый алгоритм для задачи с соединением корней Пусть Т обозначает множество деревьев, определяемых операциями соединить. Для каждой вершины v поддерживается следующая информация: рч(у), size7(v), список сыновей v в Т, такой сын w вершины v (если есть), что w—>v— тяжелая дуга, hp size(v) — количество потомков v, принадлежащих тому же тяжелому пути, что и v, и предикат light(v), означающий, что "р/(у) определено и у —> p-/(v) — легкая дуга". Можно модифицировать эту информацию за время 0(1) при выполнении одной опе- рации соединить. Операция соединить может привести к тому, что ранее тяжелая дуга станет легкой (но не обратно), а также к созданию как тяжелой, так и легкой дуги. Также поддерживается структура данных, позволяющая быстро вычислять для любой вершины v корень r7(v) того дерева из Т, которое содержит v. Изменение этой структуры данных при выполнении операций соединить и выполнение О(т) вычис- лений корня требует О(п + та(т + и, и)) времени. Соответственно Т поддерживается лес L сжатых деревьев; L содержит одно или больше деревьев, представляющих каждое дерево из Т. Деревья из L строятся семей- ство за семейством задержанным образом. Когда операция соединить создает легкую дугу v —> pi{v) или вызывает переход тяжелой дуги v —> p-i(v) в легкую, просматрива- ется тяжелый путь т, apex которого есть v, для конструирования 5 = v: w на т или p-i(w) на г}. Затем комбинируются сжатые деревья, корни которого принадлежат S, в одно сжатое дерево; v является корнем этого дерева, а вершины из S— сыновья- ми корня. В общем случае дерево D из Т представляется рядом сжатых деревьев; если г— корень D и т — тяжелый путь, apex которого есть г, то L содержит для каждой вершины v на т дерево, единственной вершиной которого является v, а для каждой такой вершины w, что p/.(w), но не w на г, дерево, вершинами которого являются все преемники w в D. На рис. 3.24 приведено множество сжатых деревьев, соответст- вующих дереву Т(см. рис. 3.19), для задачи соединения корней (см. рис. 3.20). Помимо самого леса сжатых деревьев поддерживается определенная информация о сжатых деревьях. С каждой вершиной v хранится size7(v). С каждой такой вершиной v, для которой pi.(y) определено, хранятся также p7(v) и apex(v). Изменение этой ин- формации во время операций соединить и O(/w) вычислений корня и глубины требу- ет О(п + та(т + п, п)) времени. функ NCA_T (v, iv: вершины) = 1. Вычисляются Гт(у) И Гу( w).
Глава 3. Бесконтурные графы 239 2. если гДи) * r7(w) то возврат v и w в разных деревьях 3 иначе Вычисляются /Ди) и r7(w), 4. если rL(y) * rL(w) то 5 % v и w находятся в разных сжатых деревьях % 6. v' ;= если light(r7(v)) то Дг(г7(^)) иначе д(у) все; 7 w' := если light (rL(w)) то pi[rL(v)) иначе n.(w) все; 8. возврат если hp_size(v') > hp_size(w') то v’ иначе w' все 9 иначе и .= ncajv, w); 10. % v и w находятся в одном и том же сжатом дереве % 11 если и = v или и = юо возврат и все; 12. Вычислить dL(u); 13 Найти предка v‘ вершины v в L, с глубиной dL(u) + 1; 14. v" := если apex(v') = и то и' иначе рИИ все; 15 Найти предка и/' вершины w в L, с глубиной ct(u) + 1; 16 w":= если apex(w') = и то w' иначе Pr(w') все 17. возврат если hp_size(iz") > hp_size(w") то v" иначе w" все все все все । Метод требует О(п + mcdjn + п, п)) времени плюс время, необходимое для решения m задач пса на А и 2m задач глубины на L. Рис. 3.24. Множество сбалансированных деревьев Для решения задач пса на L используется метод, описанный в разд. 3 4.4, т. е. лес L представляется лесом сбалансированных бинарных деревьев В. Если С— дерево в L, В содержит дерево D, зелеными вершинами которого являются те же, что и в С. Де- рево D строится точно так же, как описано в разд. 3.4.4; в каждый момент, когда соз- дается новое семейство в В, комбинируются соответствующие деревья в L с исполь- зованием процедуры БИНАР, если множество деревьев состоит из трех или больше
240 Часть I. Обработка и визуализация графов элементов. Для каждой вершины v поддерживается sizeB(v). Построение В и модифи- кация size информации во время операций соединить требует <?(/?) суммарного вре- мени. Задача пса для В решается путем решения задач глубины пса и глубины на В (см. разд. 3.4.4). Для решения задачи глубины пса на В дерево В встраивается в пол- ное бинарное дерево В' и используется прямой метод вычисления (см. разд. 3 4 2). Единственно, что необходимо для этого, — знать для каждой Вершины в В ее номер в симметричной нумерации и высоту (как вершины в В). Эти атрибуты должны моди- фицироваться, когда В строится. Пусть и— вершина в В с левым сыном v и правым сыном и< Когда дуги v —> и и w —> и добавляются к В, нужно модифицировать атри- буты потомков и по следующим правилам, в которых h\ = heightB(v), h2 = heightB(w) и h = max {/?(, h2}\ height в (х)-Л[ +//, если x — потомок v, heightB(x)=(/z+l, если x=w, heightв(x)-A2+Л, если x — потомок ж symB(x)= 2Л Asym/((x), если х — потомок у, 2Л+1, если х = и, 2h~h sym(x)+2/,+l, если х — потомок w. Можно использовать специальную структуру данных для поддержки этих атрибутов неявно. Общее время для поддержки структуры данных во время операций соеди- нить и вычисления О(т) атрибутов составляет О(п + та(т + п, /?)). Имея атрибуты, можно решать задачу глубины пса для В за 0(1) времени. Для решения задач глубины на L (а также на В) используется следующий метод. Раз- бивается L на O(log’/z) слоев. Определяется rank(v) = Llg(size/(v))J (см. разд. 3.4.3). Пусть функция f подчиняется правилам:/(1)= 8 и/(/) = 2/(,-|)/2 для / > 2. Определяется слой z вершины v как минимум среди таких z, что/(z) > rank(v). Слой вершины легко вычисляется в тот момент, когда определяется ее атрибут size; для этого требуется 0(1) времени, и О(«)— общее время, требуемое для вычисления слоев всех вершин. (Предполагается, что предварительно вычислена таблица, в которой для любого це- лого хе [О : Llg z?J] хранится минимум среди таких z, что/(О > х.) Общее число слоев составляет O(log* п). С каждой вершиной v хранится не только ее слой, но и ряд других значений: вершина а(у), которая является наименее глубоко расположенным предком у на том же пути, что и у; список тех сыновей v, которые лежат в том же слое, что и v; массив, индекси- рованный по глубине, всех предков v того же слоя, в котором у. Каждый раз, когда добавляется новое семейство к Л, данные атрибуты модифицируются во время обхо- да от корня г нового дерева с использованием списков сыновей для достижения всех потомков г в том же слое, где г. Общее время, затрачиваемое на модификацию этой информации, и суммарный размер массивов предков ограничен умноженной на кон- станту следующей суммой:
Гпава 3. Бесконтурные графы 241 ]1,пя решения задач глубины на L используется метод, описанный в разд. 3.4 3. Алгоритм для вычисления того предка вершины v в L, глубина которого равна <7, со- стоит в повторении до получения результата следующего основного шага: если d е [<://(«(v)): <4(v)], взять в качестве результата в массиве предков v того предка, глубина которого равна d; иначе— заменить v на p/.(a(v)). Этот метод требует 0(1) времени на однократное выполнение основного шага и O(log* и) времени на решение задачи глубины. Если хранить с каждой вершиной v текущий размер массива предков v, то можно вы- числять dL(a(y)) и dL(pL(a(v))) по dL(y) за 0(1) времени. Использование описанного метода для В и L приводит к суммарной временной оцен- ке 0(п + m log* и) для задачи с соединением корней; решение задачи глубины явля- ется наиболее трудоемкой частью алгоритма. 3.4.6. Более быстрый алгоритм для задачи с соединением корней Для того чтобы получить более эффективный алгоритм для задачи с соединением корней, нужно улучшить способ решения задач глубины на В и L. Использованный ранее способ, основанный на представлении слоев, рассмотрен в разд. 3.4.3 для вто- рого и третьего слоев. Используя метод (см. разд. 3.4.3) для первого слоя и определяя слои более динамически, можно получить следующий О(п + ma(m + п, «))—- алго- ритм решения. Задача глубины будет рассматриваться только для L, поскольку для В она решается точно так же; и обозначает количество вершин, а от — количество запросов пса, из- вестных заранее. L разбивается на три суперслоя точно так же, как в разд. 3.4.3; первый суперслой со- стоит из вершин, ранг которых меньше lg(j)n, второй — из вершин, ранг которых в диапазоне [lg<j)«: lg(2Vz- 1], и третий— из вершин, ранг которых не меньше lg(2)«. Второй и третий слои поддерживаются точно так же, как описано в разд. 3.4.5, и тре- буют на свою поддержку О(п) времени (см. разд. 3.4.3). Деревья первого слоя разбиваются на ряд поддеревьев, определение которых осно- вывается на использовании функций Аккермана А и Тарьяна а, для которых справед- ливы следующие соотношения: □ Л(0, /) =j для всех j > О, A(1,J) = У для всех J > 0; □ A(i, 0) = A(i- 1, 1) для всех i > 2, A(i,j) = A(i — 1, A(i,j— 1)) для всех i >2 и/> 1; □ a(m + п, ri) = min{Z > 1 : A(i, L(ot + w)/hJ) > 1g n}. Пусть v— такая вершина первого слоя, что p/.(v) существует. Определяется уровень вершины v как такое максимальное i е [0 : а(гп + п,«], что для некоторого j rank(v) <A(i,j) < rank(p,(v)); определяется также позиция вершины v как минимальное такоеJ. Уровень и позиция вершины, когда ее отец определен, могут быть вычислены за 0(1) при использовании небольшой заранее вычисленной таблицы.
242 Часть I. Обработка и визуализация графов Первый суперслой поддерживается как набор поддеревьев. Каждая такая его верши- на v, для которой Р/(у) неопределено, является сама одновершинным деревом. Когда для вершины v в первом слое положительного ранга определяется ее отец, строится новое поддерево Sv с корнем v. Поддерево включает всех потомков v с рангом в интервале [х: A(i,j) - 1], где г — уровень v, j — позиция v, а х определяется по сле- дующим правилам; если существуют такие целые A(j’,jr), что i < i'< a(m + и, ri),j’> 1 и A(j', j') <A(i,j), то x— максимальное из них; если такие целые не существуют, то х— максимальное целое, меньше ранга v и имеющее вид A(j', 0) для некоторого I' е [0 : г]. Можно вычислять х за 0(1) время с помощью таблицы. Определение Sv и функции Аккермана гарантирует, что множество вершин нового поддерева 5,. являет- ся объединением множеств вершин одного или больше старых поддеревьев; таким образом, в каждый момент каждая вершина находится только в одном поддереве. Указанное разбиение на поддеревья имеет следующий эффект Пусть г— наименее глубокая вершина первого слоя, v— висячий потомок г. Поддеревья разбивают путь от v до г следующим образом. Пусть I — максимальный уровень вершины на пути от v к г, и пусть х — последняя вершина пути уровня I. Поддеревья разбивают путь от v к х на сегменты (И= v, = X|), (К2,..., х2), ..., (v,,..., х,), (v/+t,..., х), (y,-h ..., w,_|), (у/_2,..., w/_2), (у,,, w„), (г), где х, для i е [1 : /] — первая вершина пути уровня i, которой пред- шествуют все вершины большего уровня, a w, для i е [0 : /] — последняя вершина пути уровня i, следующая за всеми вершинами более высокого уровня. Некоторые из v, и Wj могут быть не определены; соответствующие сегменты пути являются пусты- ми. Также возможно, что (vz,..., xz) = (vz+z,..., х). Когда pj{r) определяется, поддеревья объединяются для формирования сегмента (у„ г), где i— уровень г; если i = I, новым сегментом является (vz+i,..., г), и если / > I, новым сегментом является (vz,..., г). Для построения поддеревьев с каждой вершиной первого суперслоя хранится список ее сыновей, упорядоченных по рангу, что позволяет за время O(|S,,|) определять мно- жество вершин 5,„ просматривая от v. Если представлять каждый список сыновей в виде списка букетов, каждый из которых содержит сыновей некоторого заданного ранга, вставка нового сына требует времени, пропорционального его рангу, и свойст- во 3 4.2, Д означает, что общее время для построения этих списков сыновей состав- ляет Поддеревья первого суперслоя представляются так же, как деревья первого слоя (см. разд. 3.4.3). При этом с каждой вершиной в таком поддереве хранится ссылка на корень этого поддерева. Если Sv является одним из этих поддеревьев, конструирова- ние представления S,, требует O(|5J) времени. Время, затрачиваемое на построение всех поддеревьев первого суперслоя, ограничено величиной О(т + и). Задачи глубины решаются на £ в точности так же, как в разд. 3.4.5; при этом одна любая задача глубины решается за время О(а(т + п, «)). Описанный алгоритм решения задачи с соединением корней имеет временную слож- ность О(п + та(т + и, и)).
Глава 3. Бесконтурные графы 243 3.4.7. Заключительные замечания В предыдущих разделах рассматривались алгоритмы решения задачи пса на РАМ в предположении равномерного весового критерия, т. е. каждая ее операция (сложе- ние, сравнение или переход) осуществляется за время 0(1), и в предположении, что O(log ri) — верхняя граница на длину слова, которое может храниться в одной ячейке РАМ. (Это ограничение не позволяет строить быстрые алгоритмы за счет использо- вания эффекта параллелизма от манипуляции с очень большими целыми.) Известны решения данной задачи для другой стандартной модели вычисления — так называе- мой поинтерной машины (ПМ). В ПМ память состоит из набора вершин (иногда на- зываемых записями), каждая вершина состоит из некоторого фиксированного числа полей. С полями ассоциированы типы, такие как указательный, целый, веществен- ный. Поле некоторого заданного типа содержит значение этого типа, например, ука- зательное поле содержит указатель на некоторую вершину. Основным различием между ПМ и РАМ является то, что адресная арифметика возможна для РАМ, но не для ПМ. Табл. 3.3 содержит сложностные характеристики лучших из известных алгоритмов решения задач пса на ПМ, п — общее число вершин в деревьях, a m — общее число операций (запросов, соединений и разрезаний). А. Пусть т — полное бинарное дерево с п вершинами. Тогда независимо от пред- ставления дерева любая ПМ требует Q(log п log ri) времени в худшем случае для от- вета на любой пса запрос. Таблица 3.3. Сложностные характеристики Задача Время Память Автономная О(п + та(т + п, п)) O(w) Статические деревья О(п + т Jog log ri) O(n) С соединением корней О(п + т log log ri) O(n) С соединением О(п + т log ri) O(n) С соединением и разрезанием О(п + т log ri) O(ri) 3.5. Граф Герца Задача выявления максимальных сильно связных подграфов (бикомпонент) графа, стягивание которых в вершины делает исходный граф ациклическим, возникает во многих приложениях. 3.5.1. Бикомпоненты и граф Герца Пусть G— произвольный орграф. Компонентой сильной связности, или бикомпо- нентой В графа G называется такой его максимальный по включению вершин под-
244 Часть I. Обработка и визуализация графов граф, в котором любая упорядоченная пара вершин соединена путем. Простейшим примером компоненты сильной связности служит контур. Графом Герца (графом конденсации, фактор-графом по множеству бикомпонент) орграфа G называется граф H(G), получаемый из G стягиванием каждой бикомпо- ненты в отдельную вершину (получающиеся при этом петли удаляются). Основное свойство графа Герца выражает следующее утверждение. А. Граф Герца произвольного орграфа является бескоптурпым орграфом. Построение графа Герца включает в себя в качестве основной части отыскание мно- жества бикомпонент. 3.5.2. Матричный алгоритм отыскания бикомпонент орграфа Знание матрицы достижимости позволяет отыскать все бикомпоненты. Определим поэлементное, или адамарово, произведение матриц В~ и С= ||с/7|| по правилу: BxC=[i„x4 Тогда вершины бикомпоненты, содержащей вершину v„ определяются единичными элементами z-й строки матрицы R х R1, где R1 — транспонированная матрица дости- жимости. Отсюда следует, что, вычислив поэлементное произведение матриц R и R1 и разбив все ненулевые строки этого произведения на группы одинаковых строк, мы можем определить множества вершин каждой бикомпоненты, поскольку номера строк однозначно определяют номера вершин, входящих в бикомпоненту. 3.5.3. Алгоритм Тарьяна отыскания бикомпонент Данный алгоритм основан на поиске в глубину. Поиск в глубину в орграфе приводит к построению леса (в частном случае дерева, когда поиск в глубину начинается в единственной входной вершине орграфа, дерева) поиска в глубину S= (И, Т). Можно показать, что если В, = (Е„ Е,) — одна из бикомпонент орграфа G = (Г, Е), то верши- ны бикомпоненты В, вместе с дугами из пересечения £, с\Т образуют корневое ор- дерево и его корень называется корнем бикомпоненты В:. Бикомпоненты орграфа G можно найти, построив корни бикомпонент в том порядке, в каком они встретились в последний раз в процессе поиска в глубину на G. Пусты,, г2, rk— эти корни в том порядке, в каком заканчивался их поиск в глубину (т. е. поиск корня г, заканчивался перед поиском г,+,). Тогда для каждого i < j либо г, лежит слева от гр либо г1 — потомок вершины г, в глубинном остовном лесу. Пусть В,— бикомпонента с корнем r„ 1 < i < к. Тогда В, состоит из всех вершин, являющихся потомками вершины г, и не принадлежащих ни одному из графов I Bi, В,-\.
Глава 3 Бесконтурные графы 245 Будем считать, что вершины графа G идентифицированы их ЛУ-номерами, т. е. номе- рами, полученными в результате поиска в глубину. Для нахождения корней биком- понент введем функцию Л'[г]; 7V[v] = min({v} U {w | есть поперечная или обратная дуга из некоторого потомка вершины v в вершину w, а корень той бикомпоненты, которая содержит w, является предком вершины v}). Данное определение представлено на рис. 3.25. к. Для того чтобы вершина v была корнем бикомпоненты, необходимо и достаточ- но, чтобы Л'[г] = и. Рис. 3.25. Функция Л/ Алгоритм 3.11. Тарьяна Дано. Ориентированный граф G = (И, £). Требуется Список бикомпонент орграфа G Метод. проц ПОИСК(и) = 1. Пометить вершину и как "старую"; 2. /И[и] = номер; 3. номер := номер + 1; 4. N[v] := /ИМ; 5. Затолкнуть v в СТЕК; 6. для всех и/ е ПРЕЕМ(и) цикл 7 если вершина w помечена как "новая" то 8 ПОИСКА); 9. Л/М := min(A/[v], Л/[и/]);
246 Часть I. Обработка и визуализация графов 10. иначе если /V7[w] < и w € СТЕК то 11. N[v] := min(M[w], МИ) все все все; 12. если N[v] = M[v] то 13. повторяй Вытолкнуть х из СТЕК; print х до х = v все; 14. print "конец бикомпоненты" все; начало 1. номер := 1; 2 для всех v е V цикл пометить вершину v как "новую" все; 3. СТЕК := 0; 4. пока существует вершина v, помеченная как "новая" цикл 5. ПОИСК(у) все конец Трудоемкость алгоритма — О(тах(п, mJ). 3.5.4. Пошаговая форма алгоритма Тарьяна В том случае, если понимание алгоритма Тарьяна с использованием рекурсивной процедуры ПОИСК затруднено, имеет смысл использовать несколько видоизменен- ную его (нерекурсивную) форму. В описании алгоритма используется массив POINT. Вначале POINT(v) = 0 для всех вершин v. Это указывает на то, что ни одна из вершин еще не включена в СТЕК. POINT(v) полагается равным 1, когда v добавляется в СТЕК, и снова становится равным 0, когда v удаляется из СТЕК. Алгоритм 3.12 Шаг1. Для каждой вершины графа v положить MARK(v) = 0, FATHER(v) = 0, POINT(v) = 0. Положить i = 1 и СТЕК = 0. Ш а г 2. Выбрать произвольную вершину, например г, с MARK(r) = 0. Положить Л/(г) = z, N(r) = i, MARK(r) = 1 Добавить г в СТЕК, положить POlNT(r) = 1 и v = г. Ш а г 3. Если все дуги, исходящие из у, уже помечены как "просмотренные", то пе- рейти к шагу 5. Иначе выбрать дугу (v, w), которая еще не помечена как "просмот- ренная", пометить ее как "просмотренную" и перейти к шагу 4. Ш аг 4. Выполнить следующие действия и перейти к шагу 3: □ Если MARK(w) = 0, то положить z = z+l, M(w) = z, N(w) = z, FATHER(w) = v, MARK(w) = 1. Добавить w в СТЕК и положить POINT(w) = I и v = w. □ Если MARK(w)=l, M(w)<M(v) и POINT(w)=l, то положить N(y) = = min{A'(v), M(w)}. LU а г 5. Если 7V(v) = M(y), то удалить все вершины сверху СТЕК до вершины v вклю- чительно. Эти вершины образуют текущую бикомпоненту. Положить POINT(x) = 0 для всех вершин х, удаляемых из СТЕК.
Глава 3. Бесконтурные графы 247 Шаг 6. Если FATHER(v) = 0, перейти к шагу 7, иначе выполнить следующее: □ 7V(FATHER(v)) = min{7V(FATHER(v)), A(v)}; □ v=FATHER(v); □ перейти к шагу 3. Шаг 7. Если для каждой вершины х MARK(x) = 1, то перейти к шагу 8, иначе перей- ти к шагу 2. Шаг 8. Стоп. 3.5.5. Алгоритм Фараджева В основе данного алгоритма лежит следующая идея. Как только в процессе поиска в глубину в графе будет обнаружен контур, он немедленно стягивается в одну "составную" вершину. Кроме того, если из вершины v нет возможности продвинуться в глубь графа, то возвращение в вершину FATHERJv] сопровождается удалением v из графа. Удаленные вершины заносятся в список бикомпонент; составные вершины в нем определяют нетривиальные бикомпоненты. Незначительная модификация ал- горитма превращает его в алгоритм построения графа Герца. Алгоритм 3.13. Фараджева Дано. Ориентированный граф G = (Г, Е). Требуется. Список бикомпонент орграфа G. Метод. проц БИКОМП = 1. и:= Э СТЕК; 2. для всех w е ПРЕЕМ(и) цикл 3. если S(w) - 0 то 4. СТЕК<= иг S(w) = 1; БИКОМП 5. иначе % вершина w находится в СТЕК % 6. Свернуть часть содержимого СТЕК, начиная с вершины w до верха, в новую вершину vv, т е. удалить начиная с вершины w до верха содержимое СТЕК, запомнить удаленные вершины и вместо них занести в стек вершину w, взяв в качестве списка смежности вершины w, объединение списков смежности стянутых вершин; 7 Модифицировать списки смежности вершин графа, заменив в них стянутые вершины вершиной w ; 8. БИКОМП все все; 9. Удалить и из СТЕК и занести v в список В бикомпонент; 10. БИКОМП, все;
248 Часть I. Обработка и визуализация графов начало 1. СТЕК := 0; 2. для всех v G V цикл S(iz) = 0 все 3. для всех вершин с S(v) = 0 цикл 4. СТЕК <= у; S(v) := 1, БИКОМП все; конец Трудоемкость алгоритма O(m + и log и). 3.5.6. Алгоритм Касьянова Предполагается, что мультиграф представлен гремя массивами: □ ВЕРШИНЫ [1 : и, 1 : 2]; □ ПРЕДШЕСТВЕННИКИ [1 :/л + и]; □ ПРЕЕМНИКИ [1 : т + л]; где л— число вершин, а т— число дуг мультиграфа. Величины ВЕРШИНЫ [г, 1] и ВЕРШИНЫ [/, 2] задают соответственно имена первого предшественника и первого преемника вершины с именем z (под именем вершины понимается номер его позиции в соответствующем массиве). Предшественники и преемники каждой вершины рас- полагаются в соответствующих массивах подряд и заканчиваются нулем. Алгоритм Касьянова состоит из двух последовательных этапов: нумерации вершин графа и собственно построения его бикомпонент. На первом этапе осуществляется вспомогательная нумерация вершин графа в про- цессе построения пути обхода графа, который обозначим через Р. При этом номера вершин отражают порядок, обратный порядку их удаления из пути Р Процесс построения Р начинается включением одной из вершин в пустой путь Р. Пусть некоторый непустой путь Р построен. Если среди преемников последней вер- шины пути Р найдется вершина, ранее не включавшаяся в Р, то путь удлиняется; ес- ли же такой вершины нет, то последняя вершина пути Р удаляется из него и т. д. Пусть на некотором этапе путь Р пуст. Если существует вершина графа, ранее не включавшаяся в Р, то она включается в Р и процесс продолжается; в противном слу- чае процесс построения пути Р заканчивается. Для графа и его нумерации вершин, показанных на рис. 3.26, порядок включения вершин в путь Р следующий: 8, 11, 12, 9, 10, 4, 7, 5, 6, 3, 2, 1. Для хранения информации о пути Р в процедуре, реализующей первый этап алгорит- ма, используются два магазина: МАГ1 и МАГ2, в верхушке первого из которых все- гда находится имя последней вершины пути, а в верхушке второго— имя первого непросмотренного ее преемника. Результатом работы этого этапа является приписы- вание каждой вершине ее номера — массив НОМЕРА, и создание списка, содержа- щего имена вершин в порядке возрастания их номеров — массив ПОРЯДОК. В ходе
Глава 3. Бесконтурные графы 249 нумерации вершина с именем i еще не включалась в Р тогда и только тогда, когда НОМЕРА [/] = 0. проц НУМЕРАЦИЯ_ВЕРШИН = 1 для всех имя_вершины е [1 : л] цикл 2 НОМЕРА [имя_вершины] = 0 все; 3. текущий_номер := л; 4 для всех имя_вершины е [1 : л] цикл 5. если НОМЕРА [имя_вершины] = 0 то 6. % Включение_вершины_в_пустой_путь % 7. длина_пути := 1; НОМЕРА [имя_вершины] := 1, 8 МАП [1] := имя_вершины, 9. МАГ2 [1] := ВЕРШИНЫ [имя_вершины, 2]; 10. Дальнейшее_построение_пути: 11. начало 12. имя_преемника := МАГ2[длина_пути]; 13. преемник := ПРЕЕМНИКИ [имя_преемника]; 14 если преемник г 0 то 15 МАГ2 [длина_пути] = имя_преемника + 1; 16 если НОМЕРА [преемник] = 0 то 17. % Включение преемника в путь % 18 длина_пути := длина_пути + 1; 19. НОМЕРА [преемник] := 1; 20. МАГ1[длина_пути] := преемник; 21. МАГ2[длина_пути] := ВЕРШИНЫ[преемник, 2]
250 Часть I. Обработка и визуализация графов 22. начать Дальнейшее_построение_пути 23 иначе % Удаление последней вершины из пути % 24. последняя_вершина := МАГ1[длина_пути]; 25. НОМЕРА[последняя_вершина] := текущий_номер; 26. ЛОРЯДОК[текущий_номер] := последняя_вершина; 27. текущий_номер := текущий_номер - 1; 28. длина_пути := длина_пути - 1 29. начать Дальнейшее_построение_пути при длина_пути > 0 все все все конец все все все Наибольшее число раз выполняется "Дальнейшее построение пути". Поскольку каж- дая вершина графа включается в путь один раз, а каждый элемент списка преемников вершины пути выбирается также один раз, то этот шаг выполняется ровно п + m раз. Таким образом, этап нумерации вершин графа занимает О(п + /п) времени. На втором этапе производится собственно выделение бикомпонент. Такое выделение осуществляется при обработке вершин графа в порядке возрастания их номеров и основывается на следующих свойствах нумерации, в которых S(p) обозначает множе- ство всех тех вершин графа, из которых достижима вершина р на графе с удаленны- ми всеми теми вершинами, номера которых меньше номера вершины р: А. Для любой вершины р все вершины из S(p) принадлежат одной и той же биком- поненте. Б. Множество вершин с образует бикомпоненту графа тогда и только тогда, когда S = S(p) для некоторой вершины р, не принадлежащей ни одному S(q) таких q, что номер q меньше номера р. Рассмотрим реализацию второго этапа алгоритма, в которой массив ШКАЛА исполь- зуется для выделения необработанных вершин, а массив МНОЖЕСТВО — для по- строения множеств £(/), i е [1 : п]. проц ПОСТРОЕНИЕ_БИКОМПОНЕНТ = 1. для всех имя_вершины е [1 : л] цикл 2. ШКАЛА[имя_вершины] := О все; 3. для номер_вершины от 1 до л цикл 4. имя_вершины := ПОРЯДОК[номер_вершины]; 5. если ШКАЛА[имя_вершины] = 0 то 6. % Построение новой бикомпоненты % 7. МНОЖЕСТВО^] := имя_вершины; 8. ШКАЛА[имя_вершины] := 1;
Глава 3. Бесконтурные графы 251 9. число_элементов := имя_элемента := 1, 10. Просмотр_элементов_множества: 11. начало 12. имя_предшественника := ВЕРШИНЫ [ 13. МНОЖЕСТВО [имя_элемента], 1]; 14 Лросмотр_предшественников 15. начало 16. предшественник := ПРЕДШЕСТВЕННИКИ[имя_предшественника]; 17 если предшественник i 0 то 18 если НОМЕРА[предшественник] > номер_вершины 19. то % Дуга (предшественник, элемент) 20. включается в текущую бикомпоненту % все; 21. если ШКАЛА [предшественник] = 0 то 22. % Предшественник включается в текущую бикомпоненту % 23. ШКАЛА [предшественник] := 1; 24. число_элементов := число_элементов + 1; 25 МНОЖЕСТВО [число_элементов] := предшественник все; 26. имя_предшественника := имя_предшественника + 1; 27 начать Просмотр_предшественников 28. иначе имя_элемента := имя_элемента + 1; 29 если имя_элемента £ число_элементов 30. то начать Просмотр_элементов_множества все все конец конец все все все В процедуре ПОСТРОЕНИЕБИКОМПОНЕНТ наибольшее число раз выполняется шаг "Просмотр предшественников". Поскольку каждая вершина принадлежит ровно одной бикомпоненте и включается в нее только один раз, а каждый элемент списка исходящих дуг каждой вершины выбирается также один раз, то этот шаг выполняет- ся ровно т + п раз. Таким образом, этот этап требует О(п + т) времени. Алгоритм использует 4л + 2т ячеек памяти для хранения графа и 4и + 6 ячеек дополнительно. Первый этап алгоритма строит обратную нумерацию мультиграфа и является уточ- нением поиска в глубину для выбранного его представления. Если граф задается списком неупорядоченных дуг, то построение его представления в виде массивов ВЕРШИНЫ, ПРЕДШЕСТВЕННИКИ и ПРЕЕМНИКИ может быть осуществлено за время О(п + т). Процедура построения такова: при первом просмот- ре списка дуг подсчитывается для каждой вершины количество исходящих и заходя-
252 Часть I. Обработка и визуализация графов щих дуг. После этого распределяются места для записи предшественников и преем- ников вершин. При втором просмотре списка дуг вписывается каждый предшествен- ник и преемник на отведенные им места. Библиографический комментарий Последовательно-параллельные графы были введены Риорданом и Шенноном в [52]. Пред- ставление выражений в виде класса расширенных на деревья последовательно-параллельных графов, названных складными, которое является достаточно общим для обработки многих общих подвыражений и позволяет за полиномиальное время генерировать оптимальный код для стековых машин, было рассмотрено в [50]. Использование последовательно-параллельных графов в связанной с генерацией кода проблеме планирования было выполнено в 115]. Алгоритмы построения транзитивного замыкания разбиваются на три группы. Алгоритмы первой используют умножение матриц. Один из первых таких алгоритмов, принадлежащий Рою [54], позднее был переоткрыт Уоршаллом [78]; его трудоемкость—- О(№). Впервые улучшение алгоритма Роя-Уоршалла сделал Уоррен [77]: его алгоритм имеет ту же трудоем- кость в худшем случае, но быстрее работает в случае больших разреженных матриц. Основы- ваясь на алгоритме "четырех русских" умножения булевских матриц, Арлазаров, Диниц, Крон- род и Фараджев предложили алгоритм для бесконгурных графов с трудоемкостью O(№/iog TV) [1]. В том же 1970 г. Фурман разработал алгоритм на базе алгоритма Штрассена быстрого ум- ножения матриц [13], Мунро впервые предложил использовать предварительный переход к бесконтурному графу [45], затем появились алгоритмы Фишера и Мейера [331 и Бута |22]: все перечисленные алгоритмы имели трудоемкость О(А/|08 7 log /V). К этой же группе относятся алгоритмы [18, 2, 34, 42], основанные на замкнутых полукольцах без существенного снижения трудоемкости, а также алгоритмы Копперсмита-Винограда [27] с трудоемкостью O(№,4956log TV) и Адлемана-Бута-Препараты-Руццо [16] с трудоемкостью O(TV,°87(log TV)2’172,087 х х (log log TV),/2,°87). Второе семейство алгоритмов содержит в качестве начального шага переход к графу Герца, или графу конденсации (получаемому стягиванием каждой бикомпоненты в отдельную вер- шину) с помощью алгоритма Тарьяна [2] с трудоемкостью O(TVT). К этой группе также принад- лежат алгоритмы Торелли с трудоемкостью О(п4) [72], Пурдома с трудоемкостью О(№) [51], Эве-Курки-Суонио [31] и Эберта [30] оба с трудоемкостью O(max(TVA7, TV2)), Шмица с трудоем- костью O(TV/| М} < М |56], Жомар-Мину с трудоемкостью O(NM) [40]. В это семейство южно отнести алгоритмы, специально предназначенные для работы с бесконтурными графа- ми- алгоритм Горальчиковой-Коубека [37] с трудоемкостью O(/V-TWred), где A/red— число дуг в транзитивной редукции графа, и алгоритм К. Симона [60] с трудоемкостью O(£-37red). где к есть ”исло цепей в разложении графа на цепи [611 и [62]. отличие от алгоритмов первых двух семейств третью группу составляют алгоритмы, мини- мизирующие трудоемкость в среднем. В это семейство входят алгоритмы П. О'Нейла и Э. О'Нейла [47] с трудоемкостью в среднем О(№+Е), Блоняржа-Фишера-Мейера [21]. с трудо- емкостью в среднем О(№ log Д9, Шнорра [57] с трудоемкостью в среднем О(М'+ где М'- число дуг в транзитивном замыкании. Отдельную группу составляют параллельные алгоритмы. В работе [77] приводятся два алго- ритма нахождения транзитивного замыкания графа: первый на массиве п х и х и процессоров, второй— на массиве и2х п2 процессоров, где п— число вершин графа. Время работы обоих алгоритмов не превышает некоторой константы. На алгоритмах вычисления транзитивного замыкания на систолических массивах процессоров мы здесь не останавливаемся.
Глава 3. Бесконтурные графы 253 Алгоритм для построения транзитивного замыкания и транзитивной редукции в условиях, когда матрица смежности графа не известна заранее, предложен в работе [37]. Алгоритм замыкания относительно множества вершин принадлежит В. В. Мартынюку [10]- аналогичный алгоритм, но с трудоемкостью О(и2) был предложен ранее А. П. Ершовым [5]. Задача конгруэнтного замыкания отношения эквивалентности как задача эквивалентности выражений, называемая также задачей унификации слов, исследовалась в ряде работ [29. 42. 47 49], посвященных процедурам разрешения для формальных теорий. Специальный случай этой задачи связан с областью трансляции (см., например, [26]), где она называется задачей общих подвыражений. Приведенное в разд. 3.3 описание алгоритмов решения этой задачи базируется на [30]. Алгоритмы используют: метод реализации наборов, проанализированный в [66], такие стандартные структуры данных, как хэш-таблицы и балансированные бинарные деревья; метод TRIE-структур для хранения упорядоченных пар [64], метод представления разбиения вершин с помощью списочной структуры, описанный в [53, 591, и идею алгоритма унификации Патерсона-Вегмана [49]. Процедура КОНГРУЭНТНОЕЗАМЫКАНИЕ, описанная в разд. 3.3.1, является прямым обобщением метода нумерации значений для нахождения общих подвыражений, описанного в [26|. Неразрешимость проблемы унификации слов показана в |69]. NP-SPAСЕ-полнота проблемы унификации слов для коммутативных полугрупп была доказана в [23]. Известна [29] NP- полнота даже более простой задачи: определения по заданному множеству выражений Е, по- строенному из констант и единственной коммутативной и ассоциативной операции, наимень- шего количества операций, необходимых для вычисления всех выражений из Е. Алгоритм Ахо-Беери-Ульмана для проверки свойства "соединения без потерь" для реляцион- ных баз данных за время О(и4) был предложен в [17]; более тщательная его реализация, позво- ляющая сократить время работы алгоритма до О(и3). была описана в [43]. Задача нахождения ближайшего общего предка (или пса-задача), впервые рассмотренная в ра- боте [20], излагается в разд. 3.4 по материалам работы [39]. Сжатое дерево, рассмотренное ьразд. 3 4.3, впервые использовалось Тарьяном для вычисления функций, определенных на путях в деревьях [64]. Идея реализации процедуры БИНАР за время O(|W|) описана в [35]. Структура данных, использованная в разд. 3.4.4 для быстрого вычисления для любой вершины v корня rT(v) дерева в Т, содержащего v, описана в работах [2, 64]. Там же рассмотрена струк- тура данных, упоминаемая в разд. 5.5 в связи с быстрым вычислением и поддержанием при операциях соединения атрибутов d/(v) и г/. (v) вершин v в лесу L. В разд. 3.4.5 при решении пса-задач на В используется описанная в |64] структура данных для неявного поддержания атрибутов вершин height# и sym„. Анализ временной сложности быстрого алгоритма для зада- чи с соединением корней во многом аналогичен анализу сложности алгоритма объединения непересекающихся множеств, выполненному в [66, 67]. Ряд работ посвящен решению пса- задачи на НМ: Ахо, Хопкрофт и Ульман описали алгоритм О(п + ma(m + и, и)) для автономной задачи; предложенный Ван Лееувеным О(п + m log log и)-алгоритм для задач пса со статиче- скими деревьями и с соединением корней является в силу свойства 3.4.7, А [39] оптимальным по порядку; О(и + m log и)-алгоритм для решения пса-задач с соединением и с соединением и разрезанием был предложен Слеатором и Тарьяном [63]. Некоторые программисты указывают на то, что первые алгоритмы отыскания бикомпонент (компонент сильной связности) принадлежали программистскому фольклору. Первая публи- кация с описанием простейшего матричного алгоритма отыскания бикомпонент, как утвержда- ется в [551 без ссылок на литературу, принадлежит С. Рамамурти. В 1966 г. появился алгоритм Лейфмана [9] (см. также [6]). Наиболее эффективные алгоритмы основаны на обходе графа, представленного списками смежности, с использованием стратегии поиска в глубину. К такому
254 Часть I. Обработка и визуализация графов типу относятся алгоритмы Р. Тарьяна [65J (см. также [2, 11]). И А Фараджева [12] (см. также [4]), В. Н. Касьянова [8], а также алгоритмы А. В. Карзанова [7], В. А. Евстигнеева [3] и др. Список литературы 1 2. 3. 4 Арлазаров В. Л , Диниц Е. А., Кронрод М. А., Фараджев И. А. Об экономном построении транзитивного замыкания ориентированного графа И Докл. АН СССР. — 1970. — Т. 194 №3. —С. 487—488. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. — М.: Мир, 1979. Евстигнеев В. А. Локальный алгоритм отыскания бикомпонент в ориентированном гра фе // Журнал вычисл. матем. и мат. физики. — 1978. — Т. 18, № 5. — С. 1345—1349. Евстигнеев В. А. Применение теории графов в программировании. — М.: Наука, 1985 5. Ершов А. П. Сведение задачи распределения памяти при составлении программ к задаче раскраски вершин графов И Докл. АН СССР. — 1962. — Т. 142, №4. — С 785—787 6 Зыков А. А. Теория конечных графов. I. — Новосибирск: Наука, 1969. 7. Карзанов А. В. Экономный алгоритм нахождения бикомпонент И Тр. 3-й Зимней школы по матем. прогр. и смежным вопросам. —М., 1970. — Вып. 2. — С. 343—347. Касьянов В. Н. Об одном алгоритме выделения бикомпонент в ориентированном графе// Системное и теоретическое программирование. — Новосибирск, 1974. — С. 235—243. Лейфман Л. Я. Эффективный алгоритм разбиения ориентированного графа на бикомпо ненты // Кибернетика. — 1966. — № 5. — С. 19—23. Мартынюк В. В. Об анализе графов переходов для операторной схемы И Журн. вычисл матем. и мат. физики. — 1965. — Т. 5, № 2. — С. 293—310. Свами М., Тхуласираман К. Графы, сети и алгоритмы. — М.: Мир, 1984. Фараджев И. А. Алгоритм выделения бикомпонент ориентированного графа И Тр. 3-1 Зимней школы по матем. прогр. и смежным вопросам. — М., 1970. — Вып. 3. — С. 650— 654 Фурман М. Е. Применение метода быстрого умножения матриц к задаче нахожденш транзитивного замыкания графа И Докл. АН СССР. —- 1970. — Т. 194, № 3. — С. 530. Черняев А. П. Системы программирования для высокопроизводительных ЭВМ И Вычис- лительные науки. — М., 1990. — Т.З. — С. 1—141. — (Итоги науки и техн. ВИНИТИ АН СССР). Abdel-Wahab Н. М., Kameda Т. Scheduling to minimize maximum cumulative cost subject to series-parallel precedence constraints// Operat.Res. — 1978. — Vol. 26, N 1. — P. 141—158. Adleman L., Booth K. S., Preparata F. P., Ruzzo W. L. Improved time and space bounds for boolean multiplication // Acta Informatica. — 1978. — Vol. 11. — P 61—199 Aho A. V., Beer C., Ullman J. D. The theory of joins in rational databases// Proc. 18th Ann. IEEE Sympos. on Foundations of Computer Science. — Providence, R. I., 1977. — P 107—113. Aho A. V , Garey M. R., Ullman J D The transitive reduction of a directed graph // SIAM J Computing.— 1972. — Vol. 1. — P. 131—137. Aho A. V , Hopcroft J. E., Ullman J. D The Design and Analysis of Computers Algorithms.— Reading a.o.: Addison-Wesley, 1974. (Русский перевод см. [3]). 8 9 10 11. 12 13. 14 15. 16. 17. 18 19
Гпава 3. Бесконтурные графы 255 20. Ахо А. V., Horcroft J. Е., Ullman J D. On finding lowest common ancestors in trees // SIAM J.Computing. — 1976. —Vol. 5. — P. 115—132. 21 Bloniarz P. A., Fischer M. J., Meyer A. R. A note on average time to compute transitive clo- sure I I Automata, Languages and Programming. — Edinburgh Univ. Press, 1976. — P. 425—434. 22. Booth K. S. Boolean matrix multiplication using only O(nlos7(log n)) bit operations // SIGACT News. — 1977. 23. Cardoza E., Lipton R., Meyer A. R. Exponential spacecomplete problems for Petri nets and commutative semigroups // Proc. 8th Ann. ACM Sympos. on Theory of Computing.— Hershey, Pa, 1976, —P. 50—54. 24. Chiba N., Nashizeki T., Abe S., Ozawa T. A linear algorithm for embedding planar graphs using PQ-trees // J. Computer and System Sci. — 1985. — Vol. 30, N 1 — P. 54—76. 25. Chiba N., Onoguchi K., Nichizeki T. Drawing planar graphs nicely // Acta Informatica. — 1985 —Vol. 22. —P 187—201. 26. Cocke J., Schwartz J. T. Programming languages and their compilers: Preliminary Notes. Sec- ond Revised Version. — Courant Institute of Math. Sciences, New York, 1970. 27. Coppersmith D., Winograd S. On the asymptotic complexity of matrix multiplication // SIAM J. Computing. — 1982. — Vol. 11, N 3. — P. 472—492. 28 Downey P. J., Sethi R. Assignment commands with array references // J.Assoc.Computing Ma- chinery. — 1978. — Vol. 25, N 4. — P. 652—666. 29. Downey P. J., Sethi R., Tarjan R. E. Variations on the common subexpression problems // J. ACM. — 1980. — Vol. 27,' N 4. — P. 758—771 30. Ebert J. A sensitive transitive closure algorithm// Inform. Processing Letters.— 1981.-— Vol. 12. N 5. — P. 225—228. 31. Eve J., Kurki-Suonio R. On computing the transitive closure of a relation // Acta informatica. — 1977. — Vol. 8 — P. 308—314 32. Far)' I. On straight lines representations of planar graphs // Acta Sci. Math. Szeged. — 1948. — Vol. IL —P. 229—233. 33 Fischer M. J., Meyer A. R. Boolean matrix multiplication and transitive closure// 12th Ann. IEEE Sympos. on Switching and Automata Theory. East Lansing. MI, 1971. — P. 129—131. 34. Fletcher J. G. A more general algoritnm for computing closed semiring costs between vertices of a directed graphs // Communs. ACM. — 1980. — Vol. 23, N 6. — P. 350—351. 35. Fresman M. L. Two applications of a probabilistic search technique: sorting X+ Y and building balanced search trees// Proc. Seventh ACM Symp. on Theory of Comp. — 1975. — P. 240— 244. 36. Goetze B.. Staedler G. Algorithms on graphs with costly adjacency-information // Graphs. Hy- perhraphs and Applicatins: Proc, of the Conf, on Graph Theory. — Eyba. Oct. 1984. — 1985. — P. 41-47. 37 Goralcicova A, Koubek V. A reduct and closure algorithm for graphs// LNCS.— 1979.— Vol. 74 —P. 301—307. 38 Grunbaum B., Shephard G. The geometry of planar graphs // Proc. 8th British Comb Conf, 1981. —P. 124—150. 39. Harel D., Tarjan R. E. Fast algorithm for finding nearest common ancestors// SIAM J. Comput- ing. — 1984. — Vol. 13, N 2. — P. 338—355.
256 Часть I. Обработка и визуализация графов 40. Jaumard В., Minoux М. An efficient algorithm for transitive closure and a linear worst- case complexity result for a class of sparse graphs// Inform. Processing. Letters.— 1986. Vol. 22. —P. 163—169. 41. Kozen D. Complexity of finitely presented algebras // Proc. 9th Ann. ACM Symp. on Theory of Computing. — Boulder, Colo., 1977. — P. 164—177. 42. Lehman D. Algebraic structures for transitive closure // Theoretical. Computer. Sci. — 1977. Vol. 4. — P. 59—76. 43. Liu L., Demers A. An efficient algorithm for testing losslessness of joins in relational bases. — Tech. Rep. 78—351, Comp. Sci. Dept., Cornell. Univ., Ithaca, N.Y., 1978. data 44. Maier D. An efficient method for storing ancestor information in trees // SIAM J. Computing. 1976. —Vol. 8, —P. 599^618. 45. Munro I. Efficient determination of the transitive closure of a directed graph // Inf. Letters. — 1971.—Vol. 1. — P. 56—58. Processing 46. Nelson G., Oppen D. C. Fast decision procedures based on congruence closure // J.ACM. 1980. — Vol. 27, N 2. — P. 356—364. 47. O'Neil P. E., O'Neil E. J. A fast expected time algorithm for boolean matrix multiplication transitive closure // Inform, and Control. — 1973. — Vol. 22. — P. 132—138. and 48. Oppen D. C. Reasoning about recursively defined data structures// J. ACM.— 1980. Vol. 27, N3. —P. 403—411. 49. Paterson M.S., Wegman M. N. Linear unification// J. Computer. System. Sci.— 1978. Vol. 16. —P. 158—167. 50. Prabhala B. Efficient computation of expressions with common subexpressions // J. ACM. 1980, —Vol. 22, NL — P. 146—163. 51. Purdom P. A transitive closure algorithm // BIT. —1970. — Vol. 10. — P. 76—94. 52. 53. 54. Riordan J., Shannon С. E. The number of two terminal series parallel networks // J. Phys. — 1942. —Vol. 21. — P. 83—93. Math. Rose D. J_, Tarjan R. E., Lueker. Algorithmic aspects of vertex elimination on graphs // SIAM J. Computing. — 1976. — Vol. 5. — P. 266—283. Roy B. Transitivite et connexite// Comp. Rend. Acad. Sci. Paris.— 1959.— Vol. 249. P. 216. 55. Sattley K., Millstein R. Comments on a paper by Lowe // Communs. ACM. — 1970. — Vol. 13, N7. —P. 450—451. 56. Schmitz L. An improved transitive closure algorithm// Computer.— 1983.— Vol. 30.— P. 359—371. 57. Schnorr С. P. An algorithm for transitive closure with linear expected time // SIAM J. Comput- ing. — 1978. — Vol. 7, N 2. — P. 127—133. 58. Schonhage A. Storage modification machines// SIAM J. Computing.— 1980.— Vol. 9.— P. 490—508. 59. Sethi R. Scheduling graphs on two processors// SIAM J. Computing.— 1976.— Vol. 5.— P. 73—82. 60. Simon K. An improved algorithm for transitive closure on acyclic digraphs // Theoretical Com- puter Sci. — 1988. — Vol. 58. — P. 325—346. 61. Simon K. Finding a minimal transitive reduction in a strongly connected digraph within linear time // Leet. Notes Computer Sci. — 1990. — Vol. 411. — P. 245—259.
Глава 3. Бесконтурные графы 257 62. Simon К. On minimum flow and transitive reduction // Leet. Notes Computer Sci. — 1988. — Vol. 317 — P 535—560. 63 Sleator D., Tarjan R. E. A data structure for dynamic trees // J. Computer System Sci. — 1983. — Vol. — 26. — P. 362—391. 64 Tarjan R. E. Applications of path compression on balanced trees// J. ACM.— 1979.— Voi. 26, —P. 690—715. 65. Tarjan R. E. Depth-first search and linear graph algorithms// SIAM J. Computing. — 1972. — Vol. 1, —P. 146—160. 66. Tarjan R. E. Efficiency of a good but not linear set union algorithm// J ACM.— 1975. — Vol 22, N 2.— P. 215—225. 67 Tarjan R. E., van Leeuwen J. Worst-case analysis of setunion algorithm// J. ACM. — 1984. — Vol. 31, N 2. —P. 245—281. 68. Tarjan R. E., Yao A. C. Storing a sparse table // Commons. ACM. — 1979. — Vol. 22, N 11. — P . 606—611. 69 Tarski A., Mostowski A., Robinson R. M. Undecidable Treories. — Amsterdam: North.- Holland, 1953. 70 Thomassen C. Planarity and duallity of finite and infinite planar graphs // J. Comb. Theory. Ser. B. — 1980. — Vol. 29. — P. 244—271. 71. Thomassen C. Plane representations of graphs // Progress in Graph Theory. — Academic Press. 1984. — P. 43—69. 72. Thorelli L. E. An algorithm for computing all paths in a graph // BIT. — 1966. — Vol. 6. — P. 347—349. 73. Tutte W. T. Convex representations of graphs// Proc. London Math. Soc.— 1960.— Vol. 10. — P. 304—320. 74. Tutte W. T. How to draw a graph // Proc. London Math. Soc. — 1963. — Vol. 13. — P. 743— 768. 75. Wagner K. Bemerkungen zum Vierfarbeproblem// Jber. Deutsch. Math.-Verein.— 1936.— Bd. 46 — S. 26—32 76. Wang Biing-Feng, Chen Gen-Huey. Constant time algorithms for the transitive closure and some related graph problems on processor arrays with reconfigurable bus systems // IEEE Trans. Par- allel and Distributed System. — 1991. —Vol. 1, N 4. — P. 500—507. 77. Warren H. S. A modification of Marshall's algorithm for transitive closure of binary relations // Commons. ACM. — 1975. — Vol. 18, N 4. — P. 218—220. 78. Warshall S. A theorem on boolean matrices// J.Assoc. Computing Machinery.— 1962.— Vol. 9, — P. 11—12. 9 Зак 202
ГЛАВА 4 Сводимые и регуляризуемые графы Регуляризуемые графы представляют собой наиболее общий тип граф-моделей структурированных программ. Они поддерживают эффективное проведение оптими зирующих и распараллеливающих преобразований программ и являются основой трансформационного подхода к конструированию надежного и эффективного про граммного обеспечения. Класс сводимых и регуляризуемых графов играет чрезвычайно важную роль в про граммировании в силу того, что программа, управляющий граф которой принадпе жит этому классу, допускает применение более эффективных алгоритмов анализа оптимизации. Так, задача нахождения минимального множества дуг, удаление кото рых разрывает все контуры в орграфе, является УР-трудной для графа общего вида но имеет полиномиальную сложность для сводимых графов. и > 4.1. Класс сводимых графов Данная глава посвящена изучению свойств класса сводимых графов. В ней рассмот рены определения сводимых и регуляризуемых графов, их свойства и ряд алгоритмов решения возникающих при этом теоретико-графовых задач. Исследуются интервалы как частный случай "хорошо устроенных" графов, исследу ются их свойства, описывается алгоритм выделения максимальных интервалов i управляющем графе. Вводится понятие интервального представления управляющего графа, на основе которого определяются классы сводимых графов. Изучается обоб щенная сводимость (регуляризуемость) графов, разборность графов, а также другие свойства, эквивалентные понятию сводимости. Здесь же описывается алгоритм про- верки графов на сводимость, а также излагается связанный с ним способ определения порядка втягиваемых вершин. Решается задача регуляризации несводимых графов. 4.1.1. Уграф, фрагменты и подфрагменты Управляющим графом (уграфом) G = (X, U,p0, q0) называется ориентированный граф (X, U) с двумя выделенными вершинами: начальной р0 и конечной q0. Уграф, любая вершина которого принадлежит хотя бы одному пути по G от начальной вершины до
Глава 4. Сводимые и регуляризуемые графы 259 конечной (рис. 4.1), называется правильным. Ниже, если это не будет оговорено осо- бо, под уграфами мы будем понимать только правильные уграфы. Любой граф С, являющийся частью уграфа G, называется его фрагментом. Фрагмент С является подфрагментом фрагмента S, если С — часть S. Подфрагмент С фрагмен- та S, отличный от S, называется собственным подфрагментом. Рис. 4.1. Управляющий граф Рис. 4.2. Граничные, стартовые и финишные вершины фрагмента Вершина р фрагмента С называется начальной (соответственно выходной), если либо р = Ро (соответственно p = q^), либо в р заходит (соответственно из р исходит) дуга уграфа G, не принадлежащая С. Вершина р из С называется входной (или просто вхо- дом), если существует путь по G от р0 до р, не содержащий дуг фрагмента С. Верши- на р называется конечной для фрагмента С, если р не принадлежит С и является пре- емником хотя бы одной вершины фрагмента С. Например, для фрагмента графа G (см. рис. 4.1), порожденного вершинами {2, 3, 4}, вершина 2 и 4 — начальные, 2 — входная вершина, 4 — выходная, а 5 и 6 — ко- нечные. А. Любой вход фрагмента является его начальной вершиной, а для бикомпонент верно и обратное. Вершинар, отличная от р0 и qo, называется граничной вершиной фрагмента С, если р является начальной или выходной вершиной С. Граничная вершина р фрагмента С называется стартовой, если ЗАХОД(р) не содержит дуг из С или ИСХОД(р) состоит только из дуг фрагмента С, и финишной, если ЗАХОД(Р) состоит только из дуг фраг- мента С или ИСХОД(р) не содержит дуг из С. Например, для подграфа {5, 6, 8, 9, 10, 14, 15} уграфа G, изображенного на рис. 4.2, вершины 5 и 6 являются стартовыми, вершины 14 и 15 — финишными, а 8 — такой граничной вершиной, которая не стартовая и не финишная.
260 Часть I. Обработка и визуализация графов Простой путь Р = (pt,pr), г > 1, по уграфу G называется линейным участком (лу- чом), если ПРЕЕМ(р,) = 1 для любого i е [1 : г) и ПРЕД(р,) = 1 для любого j е (1 : г]. Например, в графе G (см. рис. 4.1) лучами являются: (1), (2), (3), (4), (5), (6), (7), (8), (2, 3). Нетривиальный сильно связный подграф уграфа называется сильно связной областью (зоной). Зона называется многовходовой, если она имеет не менее двух входов. Уграф называется одновходовым, если он не содержит многовходовых зон. Например, уграф G (см. рис. 4.1) является одновходовым; он содержит три зоны: {7}, {2, 3}, {4,5}, каждая из которых имеет по одному входу. Б. Максимальные многовходовые зоны попарно не пересекаются. В. Вершина р является начальной вершиной максимальной многовходовой зоны то- гда и только тогда, когда р является ее входом. Во многих приложениях понятие конечной вершины не используется, и при опреде- лении уграфа ограничиваются выделением только одной вершины — начальной. В этом случае свойство правильности G, которое мы обычно предполагаем по умол- чанию, — это достижимость любой вершины G от его начальной вершины. 4.1.2. Альты, гамаки и интервалы Альт — это подграф с единственной начальной вершиной. Интервал — это такой альт, начальная вершина которого принадлежит каждому его контуру; начальная вершина интервала часто называется его головной вершиной. Гамак— это такой альт, множество конечных вершин которого либо пусто, либо состоит из одной вершины, являющейся преемником каждой выходной вершины альта и не являющейся предшественником его начальной вершины. Линейной компонентой уграфа G называется гамак G, удовлетворяющий следующим свойствам: начальная и конечная (если они есть) вершины С принадлежат каждому пути по G от р0 до q0\ из конечной вершины гамака С не достижима в G начальная вершина гамака С; С не содержит собственного подграфа, который был бы гамаком и обладал первыми двумя свойствами. Например, в графе G (см. рис. 4.1) подграфы [1:7], [1:8], [2:6], {2, 3}, [4:6], {5}, {4}, {8}— гамаки, {1}, {2}, {3}, {4}, {5}, {7}, {8}, {2, 3}, {4, 6}, [4:6]— интервалы, а [1:7], {8} —линейные компоненты. А. Множество всех максимальных интервалов уграфа задает разбиение множества его вершин. Б. Если С — гамак, aS — зона, то либо S с. С, либо S= С, либо С и {q} с S, где q — конечная вершина гамака С. В. Вершина р является начальной вершиной некоторого максимального интервала уграфа G тогда и только тогда, когда либо р = р0, либо р является конечной верши- ной хотя бы одного максимального интервала уграфа G.
Гпава 4. Сводимые и регуляризуемые графы 261 Г. Подграф С уграфа G является интервалом с начальной вершиной р тогда и толь- ко тогда, когда существует такой обход F подграфа С, начинающийся с р, что для любого i е (1: г], где г = |С|, ПРЕД(^(/)) с Д. Пусть N — обратная нумерация уграфа G. Тогда для любой вершины р е X и лю- бого гамака Н либо (jT) с Н, либо Н с N{p) = 0, либо Н О {q} с Х(р), где q — конеч- ная вершина Н. Е. Множество всех линейных компонент уграфа задает разбиение множества его вершин Фрагмент называется правильным, если он имеет в точности две граничные вершины, одна из которых — стартовая, а вторая — финишная. Правильный фрагмент называ- ется простым, если он содержит одну дугу. Правильный фрагмент, не являющийся простым, называется первичным, если все его собственные правильные подфрагменты являются простыми. Рис. 4.3. Правильные и первичные фрагменты Рассмотрим фрагменты S,, S2, S3 и S4 уграфа G, изображенные на рис. 4.3. Фрагмент S] не является правильным, 83 — простой правильный фрагмент, a S2 и S4 — первич- ные фрагменты. Объединение 83 и S4— правильный фрагмент, который не является ни простым, ни первичным.
262 Часть I. Обработка и визуализация графов 4.1.3. Отношения обязательного предшествования и обязательной преемственности Вершина р обязательно предшествует вершине (или доминирует над вершиной) q в уграфе G = (X, U, р0, q(), если р принадлежит каждому пути по G от ри до q0. Она обязательно следует за вершиной (или постдоминирует) q, если р принадлежит каждому пути по G от q до q0. А. Отношение обязательного предшествования (обязательной преемственности) задает линейный порядок на множестве всех обязательных предшественников (пре- емников) любой вершины. Б. Вершина р является единственной входной вершиной фрагмента С уграфа G то- гда и только тогда, когда р принадлежит С и обязательно предшествует в G любой вершине из С. Ближайший (в смысле свойства 4.1.3, А) к данной вершине р обязательный ее пред- шественник (преемник), отличный от р, называется непосредственным обязатель- ным предшественником (преемником) вершины р. На рис. 4.4 изображены деревья D\ и D2, кодирующие отношения непосредственного обязательного предшествования и непосредственной обязательной преемственности для вершин уграфа G, приведенного на рис. 4.1. Эти деревья обычно называют де- ревьями доминатпорными и постдоминаторными. Рис. 4.4. Деревья обязательного предшествования и обязательной преемственности для управляющего графа 4.1.4. F-лучи, F-области и правильная нумерация Луч (рь ..., рг), г > 1, уграфа G называется F-лучом, где F— нумерация G, если для любого i е [1 : г) справедливо F(p) = F(pM - 1). Нумерация F называется правильной нумерацией уграфа G, если любой луч уграфа является F-лучом.
Глава 4. Сводимые и регуляризуемые графы 263 А. Прямая и обратная нумерации уграфа являются правильными. Для нумерации F уграфа G и его вершины р подграф уграфа G, множеством вершин которого являются все те вершины, из которых достижима р в подграфе 7ф:|АЦ, на- зывается F-областью и обозначается через F{p) или F(i), где i = F(p). Пусть N и М— пара связанных базисных нумераций уграфа G. Тогда: Б. Для любой вершины р уграфа G и любой вершины q е N(p) следующие свойства эквивалентны: □ q — начальная вершина Nip)', □ q — входная вершина N{p)', □ в q заходит N-прямая дуга из вершины, N-номер которой меньше N(p). В.Для любой вершины р уграфа G подграф N(p) является сильно связным, ар — его начальная вершина. Г.Для любой вершины р уграфа G ее М-номер равен min {М(сД•: q&N(p}} и каждая вершина qe.N(p) является М-достижимой из вершины р. ДДля любых двух различных вершин р и q уграфа G либо подграфы Nip) и N{q} не пересекаются, либо один из них является собственным подграфом другого. Е. Подграф S уграфа G является бикомпонентой тогда и только тогда, когда суще- ствует такая вершинар, что S = N(p) ир~& N{q) для всех q, где N(q) < N(p). Рассмотрим уграф G, изображенный на рис. 4.1. Если F— такая нумерация G, что F(i) = i для любого ze[l:8], то F(2) = {2, 3}, F(4) = {4, 6}, F(6)={6}. Алгоритм 4.1. Выделения F-области Объекты. Уграф G, каждая вершина которого может находиться в одном из двух состояний: "помечена", "непомечена" Дано. Вершина р и некоторая нумерация F уграфа G, все вершины которого поме- чены. Требуется. Выделить Ftp), сохраняя состояния вершин уграфа G. Метод. функ ОБЛАСТЬ (F: нумерация; р : вершина) = 1. А' список = {р}; В: список = {р}; 2. пока А * 0 цикл 3. q ~ё А; 4. для всех г из ПРЕД(д) цикл 5. если (F(r) > F(p)) л (г непомечена) то 6. А <- г, В <- г, пометить г, все все все;
264 Часть I. Обработка и визуализация графов 7. для всех q из В цикл А <- q; убрать пометку с q все; 8. возврат А все Ж. Временная сложность процедуры ОБЛАСТЬ составляет 0(1 + А), где / обознача- ет число вершин в Кр), a k — число дуг графа G, заходящих в вершины из Б(р). 4.1.5. Фактор-уграфы Пусть R— некоторое множество попарно непересекающихся альтов уграфа G = (X U), образующих разбиение {А), Х2, X-} некоторого подмножества YcA' и пустьХч-i =Х- Y. Говорят, что уграф G1 = (X1, U1, р'о, q'o), в котором X1 = {Хь Х2,X,.} о Хп1, получа- ется стягиванием альтов R в вершины (обозначение G1 = B(G)), если начальной (со- ответственно конечной) вершиной уграфа G1 является либо начальная вершина р0 (соответственно конечная вершина q0) уграфа G, либо альт из R, содержащий р0 (соответственно q0), а для любых А и В из X1 пара (А, В) принадлежит множеству L/1 тогда и только тогда, когда справедливо одно из следующих свойств: □ А, В е Х^ и (А, В) е U; □ А е А7+], В е RuA соединена дугой в G с некоторой вершиной из В; П А е R, В е Х-+1 и некоторая вершина из А соединена дугой с вершиной B-,A,BeR и некоторая вершина из А соединена в G с некоторой вершиной из В дугой, не принадлежащей ни А, ни В. G1 называется фактор-уграфом уграфа G относительно R. В качестве примера рассмотрим уграф G, см. рис. 4.1, и пусть В= {{2, 3}, {4, 5}} Уграф B(G), в котором вершина 1 — начальная, а 8 — конечная, имеет вид, изобра- женный на рис. 4.5. В качестве обозначений вершин уграфа B(G), соответствующих альтам исходной схемы G, используются обозначения начальных вершин этих альтов.
Глава 4. Сводимые и регуляризуемые графы 265 к. Факпюр-уграф любого уграфа G относительно множества всех нетривиальных линейных компонент G является линейным. Б. Если уграф G является одновходовым, то для любого множества R попарно непе- ресекающихся альтов уграф R(G) также будет одновходовым. 4.1.6. Интервальное представление уграфа Пусть G = (V, Е, р0) — уграф, и пусть G разбит на максимальные интервалы. Пример разбиения уграфа на максимальные интервалы приведен на рис. 4.6. Рис. 4.6. Разбиение уграфа на максимальные интервалы /(s) = {s}, /(v1) = {v1, v2, v3, v4, v5, v6, v7, v8, v9}, /(v10) = {v10}, /(v11) = {v11, v12, f} Уграф G' называется производным графом от уграфа G (обозначается G'= 1(G)), если: □ вершины v графа G' соответствуют максимальным интервалам 1(у) графа G; П вершина v в G', соответствующая интервалу /(v), соединена дугой (v, iv) с верши- ной w, соответствующей интервалу /(w), тогда и только тогда, когда в G найдется дуга, ведущая из какой-либо вершины интервала /(v) в головную вершину интер- вала /(w),
266 Часть I. Обработка и визуализация графов □ вершина л в G', соответствующая интервалу /(s), является его начальной вер- шиной. Другими словами, производный уграф /(G) получается из G стягиванием максималь- ных интервалов в вершины, т. е. представляет собой фактор-уграф уграфа G по мно- жеству его максимальных интервалов /. Последовательность Go = G, G|, ..., G* уграфов такая, что = G* и для всех i, 1 <i <k, граф G, является производным от G,_t, называется интервальным представ- лением уграфа G (рис. 4.7). Рис. 4.7. Интервальное представление уграфа Для любого г уграф G„ являющийся элементом последовательности интервального представления уграфа G, называется r-производным от уграфа G, уграф Gk, завер- шающий последовательность, называется предельным уграфом от G, а А— длина интервального представления G. Алгоритм 4.2. Выделение максимальных интервалов Дано. Уграф G = (X, U, р0, q0). Требуется. Разметить уграф G, сопоставляя каждой вершине р уграфа G ту вер- шину, которая является начальной у максимального интервала уграфа G, содержа- щего р. Метод. проц МАКСИМАЛЬНЫЕ-ИНТЕРВАЛЫ = 1. КНД : разметка = {(р, ПРЕД(р)): р е X}; 2. НАЧАЛО : разметка = {(р, О): р * ро} и{(ро, Ро)}; 3. НАЧВЕР : список = {ро};
Глава 4. Сводимые и регуляризуемые графы 267 4. пока НАЧВЕР * 0 цикл; 5. р := Э НАЧВЕР; А := {р}; В := 0; 6. повторять q .= Э А; 7. для всех v из ПРЕЕМ(д) цикл 8. КНД(и) := КНД(у) - 1; 9. если (КНД(у) = 0) л (HA4AJlO(v)=Q) то 10. НАЧАПО(у) :=р;А<-р 11. иначе В <-v все все 12. до А = 0 все; 13. пока В * 0 цикл 14. q := ЭВ; 15. если НАЧАЛО(д) = Q то 16. НАЧАЛО(д) := q; НАЧВЕР <- q все все все все Разметка КНД задает для каждой вершины р количество еще не обработанных дуг, заходящих в р, а НАЧВЕР состоит из всех тех необработанных начальных вершин q максимальных интервалов, что либо q=po, либо обработана хотя бы одна из дуг, за- ходящих в q. Алгоритм опирается на свойства 4.1.2, В и 4.1.2, Г. Работа алгоритма состоит в том, что, начиная с НАЧВЕР = {р0} (оператор 3), он для каждой р 6 НАЧВЕР выделяет максимальный интервал с начальной вершиной р (операто- ры 5—11). После выделения интервала множество В содержит некоторые вершины данного интервала и все его конечные вершины. Операторы 13—16 включают в НАЧВЕР все те конечные вершины выделенного интервала, которые туда не вклю- чались. А. Временная сложность алгоритма 4.2 составляет О(т), где т — число дугуграфа G. 4.1.7. Интервально-сводимые уграфы Уграф G = (V,E,po) называется (интервально) сводимым уграфом, если является тривиальным (т. е. пустым одновершинным) графом предельный уграф от G, и (ин- тервал ыю) несводимым — в противном случае. Интервальное представление своди- мого уграфа называется его стандартным представлением. Граф на рис. 4.6 является сводимым; его интервальное представление изображено на рис. 4.7. Существуют несводимые уграфы; на рис. 4.8 приведен пример такого графа. Его интервальное представление заканчивается нетривиальным графом. Теорема Касьянова. Классы сводимых, одновходовых, регуляризуемых и аранжи- руемых уграфов совпадают. Определения регуляризуемых и аранжируемых уграфов см. в разд. 4.1.3 и 4.1.4.
268 Часть I. Обработка и визуализация графов Рис. 4.8. Интервальное представление несводимого уграфа Говорят, что уграф G содержит запрещенный подграф (рис. 4.9), если в G существу- ют такие различные вершины рь р2 и рз, что найдутся попарно непересекающиеся по внутренним вершинам простые пути Po.i, Г*, 2, Р\,з, Рг,з, ^3,2, гДе Рц обозначает путь от вершины pi до вершины р, и в качестве р0 рассматривается начальная вершина уграфа G. Рис. 4.9. Запрещенный подграф
Гпава 4 Сводимые и регуляризуемые графы 269 Каркасом уграфа G называется такой ациклический уграф К, что К— такой остов уграфа С, что добавление в него еще одной любой дуги уграфа С нарушает его ацик- личность. Теорема Хехта — Ульмана. Следующие свойствауграфа G = (И, Е, р0) эквивалент- ны: G является сводимым уграфом', G не содержит запрещенного подграфа', G име- ет единственный каркас, существует разбиение множества дуг Е на два подмно- жества Е\ и Ei, что (К, Eh р0) — каркас уграфа G, а для любой дуги (р, q) е £2 вер- шина q обязательно предшествует вершине р в G. 4.1.8. Регуляризуемые уграфы Уграф G называется регуляризуемым (обобщенно сводимым), если существует после- довательность уграфов Go = G, Gb ..., G*, называемая последовательностью сведения G, в которой Gk— тривиальный граф, а каждый следующий член последовательно- сти G, получается из предыдущего G,, стягиванием некоторого непустого множества попарно непересекающихся интервалов в вершины. На рис. 4.10 приведен пример регуляризуемого уграфа G вместе с его последователь- ностью сведения. В уграфе G начальной является вершина I. Рис. 4.10. Последовательность сведения регуляризуемого уграфа
270 Часть I. Обработка и визуализация графов Из определения следует, что любой сводимый уграф является регуляризуемым, но верно и обратное. А. Любой регуляризуемый уграф является сводимым. Последовательность уграфов Go = G, G\,Gr называется зонно-интервальным пред- ставлением уграфа G, если граф Gr не содержит зон, а для любого i граф получа- ется из Gi-i стягиванием в вершины элементов непустого множества попарно непе- ресекающихся интервалов, являющихся зонами. Свойство регуляризуемости уграфа G может быть охарактеризовано в терминах его //-областей. Говорят, что множество А зон уграфа G образует иерархию вложенных зон, если справедливы следующие два свойства: □ любая пара зон .$!, S2 из А либо не пересекается, либо одна из этих зон целиком содержится в другой; □ для любой зоны Si уграфа G существует такая зона S2 е А, что S| с S2 и у зон S, и S2 есть общая входная вершина. Б. Множество всех нетривиальных N-областей уграфа G является ее иерархией вложенных зон На основе свойства 4.1.8, Б построение иерархии вложенных зон уграфа G можно осуществить, выполняя следующую функцию: функ ИЕРАРХИЯ-ВЛОЖЕННЫХ-ЗОН (G : уграф) = 1. Z: множество зон = 0; 2. Построить обратную нумерацию N уграфа G; 3. для всех р из множества вершин уграфа G цикл 4. Включить в Z нетривиальную зону Л/(р>, выделенную с помощью алгоритма 4.1 все; 5. возврат Z все Временная сложность такого построения не превышает О(тп), где п и т — это коли- чество вершин и дуг уграфа G. Другой способ построения иерархии вложенных зон описывается следующей функ- цией. функ ИЕРАРХИЯ-ВЛОЖЕННЫХ-ЗОН-1 (С: уграф; р : вершина) = 1. Z: множество зон = 0; 2. Включить в Z все нетривиальные бикомпоненты графа, полученного из С удалением всех дуг, заходящих в р; 3. для всех S из Z цикл 4. Пусть q — одна из начальных вершин S; 5. Z <= ИЕРАРХИЯ-ВЛОЖЕННЫХ-ЗОН-1(Б, q) все; 6. возврат Z все
Глава 4. Сводимые и регуляризуемые графы 271 Обращение ИЕРАРХИЯ-ВЛОЖЕННЫХ-ЗОН-!(С, ро) позволяет осуществлять по- строение иерархии вложенных зон за время, не превышающее О(тп). Пусть Z— множество всех нетривиальных TV-областей уграфа G. Для каждой зоны S е Z рассмотрим ее уровень h(S), равный нулю, когда B(S) = {S' е Z: S' с S} = 0, и равный max {/?(£'): S' е Z и S' с S} + 1, когда B(S) * 0. Пусть г— максимальный уро- вень зон из Z, и пусть для любого i через Z, обозначается множество всех таких S е Z, что либо h(S) = i, либо h(S) < i и нет зон S' е Z, что S с: S'. В. Уграф G является регуляризуемые тогда и только тогда, когда Go = G, Z0(G), Z,_|(G),..., Zr(G) является зонно-интервальным представлением уграфа G. 4.1.9. Аранжировка и аранжируемые графы Нумерация F альта С, при которой каждый простой путь по С от его начальной вер- шины является F-путем, называется аранжировкой. Альт называется аранжируемым, если существует его аранжировка, и пеаранжируе- мым— в противном случае. На рис. 4.11 приведены примеры аранжируемого и неаранжируемого альтов С| и С2, в которых начальной является вершина 1. Рис. 4.11. Пример аранжируемого альта Ci и неаранжируемого альта С2 к. Любой интервал аранжируем. Г>.Дуга (p,q) является F-обратной для аранжировки F уграфа G тогда и только тогда, когда вершина q обязательно предшествует вершине р. В. Если существует некоторое множество R попарно непересекающихся и аранжи- руемых альтов уграфа G таких, что уграф R(G) аранжируемый, то уграф G явля- ется аранжируемым.
272 Часть I. Обработка и визуализация графов Г. Для любого простого пути Р по G от ро существует такой каркас К уграфа G, что Р является путем по G. Д. Пусть G— аранжируемый уграф и F— некоторая его аранжировка. Вершина р обязательно предшествует вершине q в G тогда и только тогда, когда р принадле- жит каждому простому F-nymu от ро до q. Дуга аранжируемого уграфа G называется дугой назад, если она является F-обратной дугой для любой аранжировки F уграфа G, и дугой вперед, если она является F-прямой для любой аранжировки F уграфа G. Е. Каждая дуга аранжируемого уграфа G является либо дугой вперед, либо дугой назад Ж. Каркас аранжируемого уграфа G может быть получен из G удалением всех его дуг назад. Глубиной, или числом несоответствия нумерации F уграфа G, называется наиболь- шее число F-обратных дуг, принадлежащих простому пути по у графу G. Глубиной аранжируемого уграфа G (обозначение d(G)) называется глубина его любой аранжировки. Например, глубина d(Cx), где G — уграф (см. рис. 4.6), равна трем, поскольку про- стой путь (6, 5, 7, 2, 3) содержит все три дуги назад (6, 5), (7, 2) и (2, 3) уграфа Сх. 3. Для любого сводимого уграфа G справедливо неравенство d(G) < 1(G), где d(G) — глубина G, a 1(G) — длина его интервального представления. Нумерация F уграфа G называется разумной, если справедливы следующие два свой- ства: П F(p) < F(q) для любых двух таких различных вершин р и q, что р обязательно предшествует q', □ если G — аранжируемый уграф, то F является аранжировкой. И. Обратная нумерация уграфа является его разумной нумерацией. Заметим, что не у всех уграфов прямая нумерация будет разумной. 4.1.10. Разборные уграфы Введем в рассмотрение следующие два преобразования: TI — удаление петли и Т2 — слияние двух вершин (рис. 4.12). Преобразование Т1 определено для любой вершины р уграфа и состоит в удалении дуги (р, р) из уграфа, если она есть. Преобразование Т2 определено только для такой пары вершин р и q, что вершина|? не является начальной вершиной уграфа и имеет единственным предшественником вершину р. Результатом применения Т2 является удаление вершины q вместе с дугой (р, q) и добавление множества ПРЕЕМ(г?) в множество ПРЕЕМ(р). Другими словами, происходит втягивание вершины q в вершину р таким образом, что дуга (р, q) удаля- ется из уграфа, а все дуги, ранее исходившие из q, становятся дугами, исходящими из вершины р.
Глава 4. Сводимые и регуляризуемые графы 273 Рис. 4.12. Преобразования разборного уграфа Уграф называется разборным (или сводимым по Хехту и Ульману), если он может быть преобразован в тривиальный граф с помощью последовательного применения преобразований Т1 и Т2. А. Интервал является разборным уграфом. Б. Уграф разборен тогда и только тогда, когда он сводим. Рассмотрим преобразование Т2', определяемое следующим образом. Пусть р и q, p*q, — две вершины в уграфе G с начальной вершиной 5. Если (р, q)— единствен- ная дуга, заходящая в q, и q*s, то Т2' определено. Оно удаляет вершину q и инци- дентные ей дуги, а вместо каждой удаленной дуги (q, х) с х * р добавляется дуга (р, х) (если она ранее не присутствовала в графе), а также дуга (х, р) вместо каждой дуги (х, q) для х * q, если дуга (х, р) не была ранее в графе. В. Уграф G является разборным тогда и только тогда, когда уграф, полученный из G удалением всех петель, может быть преобразован в тривиальный с помощью пре- образования 72'. Использование модифицированного преобразования Т2' позволяет осуществить про- верку уграфа на сводимость с трудоемкостью О(п), а с использованием более тонкой техники модификации информации после применения преобразования Т2'— с тру- доемкостью O(/??-log т). 4.1.11. Алгоритм проверки сводимости графа --------Задача---------- Объекты. Рассматриваются уграфы, в которых проведен поиск в глубину, верши- нам присвоены М- и TV-номера, а все дуги разбиты на классы древесных, прямых, по- перечных и обратных дуг. Для каждой вершины w определены: C(w) — множество начал обратных дуг, заходящих в w; P(w)— множество вершин, из которых существует путь хотя бы в одну вершину из C(w), не содержащий w. Операции. НАИТИ(х) — функция, возвращающая имя множества, содержащегох. ОБЪЕДИНЕНИЕ^, В, С) — процедура, вычисляющая объединение множеств А и В (уничтожая множества А и В) и дающая новому множеству имя С.
274 Часть I. Обработка и визуализация графов Н(х) — имя первой вершины, в которую втягивается вершина х (Я(х) полагается рав- ной 0, если х никогда не втягивается). ND(y) — число потомков вершины v. Дано. Уграф G = (Г, Е, s'). Требуется. Ответить на вопрос: "Сводим или нет граф G?" -----Решение-------- Метод. проц ПРОВЕРКАМ. уграф)= 1. Вычислить ND(v) для каждой вершины v; 2. для v от 1 до п шаг 1 цикл 3. Построить списки всех обратных, прямых и поперечных дуг, заходящих в v; 4 Сконструировать множество с именем v, содержащее v в качестве единственного элемента; 5. Н(у) := 0; все; 6. для iv от п до 1 шаг -1 цикл 7. Р := 0; 8. для каждой обратной дуги (у, iv), заходящей в iv, цикл 9. Включить НАЙТИ(|/) в Р; 10. Q := Р; 11. пока Q*0 цикл 12. Выбрать вершину х е Q и удалить ее из Q; 13. для каждой древесной, прямой или поперечной дуги (у,х), заходящей в х, цикл 14. у’ := НАЙТИ(у); 15. если w > у' л w + ND(w) < у' то на 20 все; 16. если у' £ Рл у’ф iv то добавить у'к Р и Q все; 17. если /-/(у) = 0 то Н(у) := w все; все; все; все; 18. для х е Р цикл ОБЪЕДИНЕНИЕ^, iv, iv) все; все; 19. стоп % Уграф сводим %; 20. стоп % Уграф несводим % конец В основе алгоритма лежит следующая идея. Пусть 7{G) есть дерево поиска в глубину для графа G, и пусть w, > w2 > ... > w„— вершины из G, в которые заходят обратные дуги. Вычислим P(w,). Если в Р(и’|) найдется некоторая вершина, не являющаяся по-
Гпава 4. Сводимые и регуляризуемые графы 275 томком wi, то граф несводим; в противном случае втягиваем вершины из P(w1) ви| и в образовавшемся графе G' вычисляем P'(w2). Если в P'(w2) найдется вершина, не яв- ляющаяся потомком вершины и>2, то стоп; в противном случае формируем граф G" втягиванием вершин из P'(w2) в w2 и вычисляем Р"(ыз) в G". Граф сводим, если дан- ной процедурой можно избавиться от всех обратных дуг. Это утверждение есть след- ствие следующих. А. Граф G сводим тогда и только тогда, когда для всех w и всех v е P(w) в дереве поиска в глубину T(G) существует путь uswev. Пусть w есть вершина с наибольшим ЛАномером в G, в которую заходит обратная дуга. Предположим, что для всех v е P(w) существует путь из v в w по древесным дугам дерева T(G). Пусть G' образуется из G втягиванием всех вершин из P(w) в w. Б. Каждая дуга (v', w') в G' соответствует дуге (v, и,г) в G, такой, что в T(G) суще- ствует путь из v'в V. Пусть Т— суграф графа G', дуги которого соответствуют дугам из T(G). В, Дерево Г с тем же упорядочением вершин, что и в T(G), есть дерево поиска в глубину в G'. Обратные дуги G' соответствуют дугам G, прямые дуги G' соответ- ствуют прямым или поперечным дугам G, поперечные дуги G' — поперечным дугам G. Пусть множества Р'(х) и С'(х) определены в графе G' так же, как и множества Р(х) и С(х) в графе G. Г. Для любой вершины х < w в Т' существует путь из х в у для всех у е Р'(х) тогда и только тогда, когда в Т существует путь изх в у для всех у е Р(х). Для оценки трудоемкости алгоритма заметим, что шаги 1—5 имеют трудоемкость 0(п + т). Нетрудно проверить, что величины ND(y) могут быть вычислены во время поиска в глубину. Каждая обратная дуга в G проверяется в точности один раз на ша- гах 9—18. Один раз вершина становится элементом множества Р (равного P(w) для текущей вершины w), втягивается в некоторую другую вершину, и составляющие ее вершины больше никогда не перепроверяются. Таким образом, каждая прямая, дре- весная и поперечная дуга проверяется в точности один раз на шагах 13—17. Отсюда следует, что цикл 6—18 требует О(п+т) шагов плюс О(и) шагов для процедур ОБЪЕДИНЕНИЕ и О(т) для НАЙТИ. Тонкий момент в этом алгоритме — формирование графов G', G" и т. д. втягиванием вершин. Для повышения эффективности алгоритма нужно использовать эффектив- ную процедуру объединения непересекающихся множеств. Множество с именем v будет содержать вершину v и все вершины, втянутые в v в текущем графе. Вначале будут существовать п множеств с именами содержащихся в них вершин. Функция НАЙТИ(х) будет возвращать имя множества, содержащего х, т е имя вершины, ко- торая соответствует X в текущем графе. Полная трудоемкость алгоритма определяется трудоемкостью операций над множе- ствами. что составляет при эффективном способе построения объединения множеств 0(min{w log п + т, т log*л?}) или, более точно, О(та(т, и)), где а(т, п) — очень мед- ленно растущая функция, которая связана с обращением функции Аккермана k(p,q) и определяется следующим образом: сДт, п) = min{z > 3 | A(z, 4 Гт/п 1) > log2 п}.
276 Часть I. Обработка и визуализация графов Функция Аккермана имеет вид: А(р,д) = - 2<7, О, 2 Р = О; Р = О, р > I; р>1, <7=1; р>1, <7>2. |А(р-1, А(р, <?-!)), Отметим, что функция Аккермана является очень быстро растущей функцией. По- этому А(3,4) — очень большое число, и можно показать, что а(/л, п) < 3, если m * и и log2 и < А(3,4). 4.1.12. Упрощенный вариант алгоритма Ниже мы приведем более простой вариант описанного выше алгоритма. Достоинство его в прозрачности шагов. Пусть Н\(у)— такой наибольший собственный (т. е. не равный v) предок вершины v, что существует путь Р из v в Wl(v) и Р не включает в себя собственных предков v, исключая Мы полагаем //l(v) = 0, если не суще- ствует пути из v в какой-либо собственный предок v. На рис. 4.13 в скобках указаны Н1(у) для соответствующих вершин. Рис. 4.13. Уграф, вершинам v которого сопоставлены величины Л/!(т) Сводимость графа в терминах величин Wl(v) может быть выражена следующим об- разом. А. Граф G сводим тогда и только тогда, когда нет таких вершины v и дуги (и, v), заходящей в v, что w < Н\ (v), где w — наибольший общий предок и и v.
Гпава 4. Сводимые и регуляризуемые графы 277 Отсюда получаем следующий метод проверки сводимости уграфа: 1. Выполнить поиск в глубину в графе G с s в качестве начала поиска. 2. Вычислить Н1(у) для каждой вершины v в графе G. 3. Для поперечных дуг проверить при вычислении Н\(у) выполнение условий свой- ства 4.1 12, А. 4. Для прямых дуг проверить после вычисления /71(v) выполнение условий свойства 4.1.12, А. При этом прямые дуги могут игнорироваться при вычислении Н1(у), а обратные дуги могут не учитываться при проверке условий свойства 4.1.12, А. Для вычисления значений Н\(у) вначале упорядочиваются обратные дуги (и, v) по М-номерам v. Затем обратные дуги обрабатываются в порядке убывания Л7-номеров вершин и. Чтобы обработать обратную дугу (w,v), мы должны подниматься вдоль пу- ти в дереве из и в v, помечая (вначале все вершины непомечены) каждую текущую непомеченную вершину ЛТ-номером вершины v. (При этом сама вершина v остается непомеченной.) Если вершина w уже помечена, то проверяем все поперечные дуги, заходящие в w. Если (z, v) — такая дуга (рис. 4.14), то мы поднимаемся вдоль пути в дереве из z в v, помечая каждую непомеченную дугу ЛТ-номером вершины v. Если z не является потомком v, то граф G несводим по свойству 4.1.12, А, и алгоритм за- вершает свою работу. В противном случае мы продолжаем помечать вершины, пока не будут рассмотрены все поперечные дуги, входящие в уже помеченные вершины, после чего рассматривается следующая обратная дуга. После рассмотрения всех об- ратных дуг метки будут представлять собой значения Н\(у) для соответствующих вершин. Оставшиеся непомеченные вершины имеют значения Н\(у), равные 0. Рис. 4.14. Обработка обратной дуги (и, v); (z. w) является поперечной дугой В предлагаемом варианте алгоритма Тарьяна, реализующим данный метод проверки сводимости уграфа, используются и очередей BUCKET(w) по одной для каждой вер-
278 Часть /. Обработка и визуализация графов шины w. Каждая такая очередь BUCKETCw) содержит список обратных дуг {u, w), заходящих в вершину w. При обработке обратной дуги (д, w) вершины, из которых можно попасть в и, хранятся в множестве CHECK. Алгоритм 4.3. Упрощенный алгоритм проверки сводимости Дано. Управляющий граф G = (У, Е, s). Требуется. Ответ на вопрос: "Сводим или нет граф G?" Метод. проц ПР0ВЕРКА2(6: уграф)= 1. Выполнить поиск в глубину на данном графе G, обозначить вершины их Л4-номерами, упорядочить обратные дуги (и, v) по /W-номерам вершин v. 2 для всех / е [1 ,л] цикл Н1(/) := 0 ; BUCKET(/) := 0 все; 3. Поместить обратные дуги (u,w) в BUCKET(iv); 4. w := п - 1; 5 на 7 если BUCKET(w) * все 6. w.= w- 1; если w< 1 то на 16 иначе на 5 все; 7. Начало обработки новой обратной дуги: (x.w) Э BUCKET(w); CHECK := {х}. 8. Завершение обработки обратной дуги: если CHECK = 0 то на 5 иначе на 9 все; 9. Удалить и из CHECK; 10 на 18 если и — не потомок w все; 11. на 8 если и = w все; 12. на 15если Н1 (и)*0 все; 13. H1(u):=w; 14. для каждой поперечной дуги (v,u) цикл v => CHECK все; 15. u := FATHER(u); на 11; 16. если и > H'l(v) для каждой прямой дуги (и, v) то 17. стоп % Граф сводим % все; 18. стоп % Граф несводим % конец Шаг 10 требует умения определять, является ли вершина w потомком другой верши- ны и. Пусть, как и в более полной версии алгоритма, ND(u) есть число потомков вер- шины и в Т. Нетрудно показать, что w— потомок и тогда и только тогда, когда и < w < и + ND(u). 4.1.13. Порядок втягивания вершин Алгоритм проверки графа на сводимость в обоих описанных вариантах неконструк- тивен в том смысле, что он не дает нам порядка, в котором необходимо втягивать вершины при сведении сводимого графа. Однако всю нужную информацию можно
Глава 4. Сводимые и регуляризуемые графы 279 получить во время работы алгоритма. С этой целью будем использовать ^ну- мерацию вершин уграфа. Известно, что TV-номера вершин удовлетворяют следующим соотношениям: □ если (v, w) — древесная дуга, то N(y) < TV(w); П если (v, и’) — прямая дуга, то N(y) < N(w); □ если (у, и) — обратная дуга, то N(y) > N(w); □ если (v, и) — поперечная дуга, то N(y) > N(w). На рис. 4.13 TV-номера вершин указаны в прямоугольных рамочках. Предположим, что каждый раз, приписывая вершине ненулевую величину Н\(у), мы будем приписывать ей пару 7V(v)). Когда алгоритм заканчивается, мы упоря- дочиваем вершины так, что вершина, помеченная парой (xi,yi), появляется раньше вершины, помеченной парой (х2, у2) тогда и только тогда, когда Х] >х2 или Х| = х2 и У1 < у2- Это упорядочение вершин называется редукционным порядком. Отметим, что непомеченной вершине v приписывается пара (0, N(y)). Для графа (см. рис. 4.13) порядком редукции является следующая последователь- ность вершин: 4 с меткой (3,4), 5 с меткой (3,8), 3 с меткой (2,3), 8 с меткой (2,5), 10 с меткой (2,6), 9 с меткой (2,7), 7 с меткой (2,9), 6 с меткой (2,10), 2 с меткой (1,2). 4.1.14. Преобразование несводимых графов Существует ряд подходов к преобразованию программы с несводимым управляю- щим графом в эквивалентную программу, управляющий граф которой сводим. Мы ограничимся рассмотрением тех из них, которые не требуют другой информации о программе, кроме ее управляющего графа, и, изменяя программу, не увеличивают времени счета по ней. Все рассматриваемые преобразования связаны с дублировани- ем (копированием) некоторых операторов исходной программы и в терминах поме- ченного графа формулируются как преобразования исходного несводимого графа G в эквивалентный ему сводимый граф. Пусть имеется множество символов Е, называемых операторами, и пусть вершины графа G помечены символами из Е таким образом, что для любых вершин р и q вы- полняется |ИСХОД(р)| = |ИСХОД(<у)|, если пометки р и q совпадают, т. е. £(р) = L(q), где£— разметка, сопоставляющая каждой вершине р графа G оператор L(p) е Е. Если Р— некоторый путь (р\,р2, —,рд по графу G, то через ЦР) обозначается слово £(pi)£(d2) ... £(рг) в алфавите Е, т. е. £(р) е Е . Говорят, что путь Р несет слово £(£’). Два помеченных графа G, и G2 называются эквивалентными, если для любого пути Р от начальной вершины любого из графов найдется такой путь R от начальной верши- ны в другом графе, что пути Р и R несут одно и то же слово. На рис. 4.15 приведены два эквивалентных уграфа. 4.1.15. Преобразования расщепления Через ТЗ обозначим расщепление вершины — такое эквивалентное преобразование графа, при котором некоторая вершина р, отличная от р0 и q0 и не имеющая петли
280 Часть I. Обработка и визуализация графов Рис. 4.15. Эквивалентные уграфы (/?,/?), заменяется на г= |ПРЕД(/?)| экземпляров р\,рг по одному для каждой вер- шины q из ПРЕД(р). Другими словами, вершина р заменяется на вершины р\, ...,рг таким образом, что L(p,) = L(p) и ПРЕЕМ(/?,) = ПРЕЕМ(/?) для всех i e fl, г], а множе- ства ПРЕДО?,), ••• ПРЕДО?,) образуют разбиение множества ПРЕДО?) на одноэле- ментные подмножества. На рис. 4.15 приведен пример использования преобразования ТЗ: вершина 2 расщеп- лена на два экземпляра— 5 и 6. К графу, изображенному на рис. 4.16, преобразова- ние ТЗ не применимо. Рис. 4.16. Пример уграфа, к которому не применимо преобразование ТЗ А. Любой граф G с помощью преобразований Tl, Т2 и ТЗ приводится к тривиаль- ному. Пусть С— сводимый альт графа G с начальной вершиной р, не являющийся собст- венным подграфом другого сводимого альта графа G и не содержащий вершин и до- Тогда к С применимо преобразование Т4, называемое расщеплением альтов. Т4 — это эквивалентное преобразование, которое заменяет альт С на столько его эк- земпляров, сколько разных дуг, не принадлежащих С, заходят в начальную вершину С. При этом в графе G каждая дуга (/?, д), исходящая из С, заменяется на дуги (pi, q),..., (pr, q), где pt, ...,рг— все экземпляры вершины р. Заметим, что Т4 приме- нимо только к несводимым графам, и если расщепляется тривиальный альт, то дейст- вие Т4 совпадает с действием ТЗ. Результат применения преобразования Т4 показан на рис. 4 17: вершины 9 и 12 в графе, полученном после расщепления альта [2, 4], соответствуют вершине 2, вер- шины 10 и 13 — вершине 3, а вершины 11 и 14 — вершине 4.
Глава 4. Сводимые и регуляризуемые графы 281 Рис. 4.17. Пример выполнения преобразования Т4 Б. С помощью преобразования Т4 можно преобразовать любой граф в эквивалент- нын ему сводимый граф Расщепление многовходовых зон (обозначаем Т5)— это такое эквивалентное преоб- разование графа G, при котором одна из максимальных многовходовых зон графа заменяется на г экземпляров (где г— число начальных вершин расщепляемой зоны) таким образом, что каждая дуга (p,q), где р и q— выходная и конечная вершины зоны, заменяется на г дуг (р\, q), ..., (р„ q), где р\,..., рГ— экземпляры вершины р, а новым преемником предшественников i-ii начальной вершины зоны становится /-я начальная вершина /-го экземпляра зоны. На рис. 4.18 (слева) приведен результат применения преобразования Т5 к графу G, представленному на рис. 4.17. Применяется преобразования Т5 к двухвходовой зоне {2, 3, 5, 6} и заменяет ее на две зоны— [9, 12] и [13, 16]— по одной для каждого входа расщепляемой зоны. %. Преобразование Т5 позволяет преобразовать любой граф в эквивалентный ему сводимый граф. Пусть каждому символу оператора из £ сопоставлено положительное число — вес этого оператора (например, в качестве веса оператора может рассматриваться объем памяти, необходимой для его хранения). Тогда весом некоторого графа а называется сумма весов его вершин (вес вершины — это вес оператора, символ которого ей со- поставлен). Экономной расклейкой графа G называется такой эквивалентный ему сводимый граф, вес которого равен минимуму из весов сводимых графов, эквивалентных гра- фу G Г. С помощью расщеплений не всегда можно получить экономную расклейку своди- мого графа.
282 Часть I. Обработка и визуализация графов Рис. 4.18. Примеры выполнения преобразований Т5 (слева) и Тб (справа) 4.1.16. Стандартное преобразование Пусть р— некоторая вершина графа G, принадлежащая некоторой многовходовой зоне графа G, и пусть S — максимальная многовходовая зона, содержащая р. Тогда определено стандартное преобразование (обозначаем Тб) графа G относительно вершины р. Тб — это такое эквивалентное преобразование, которое копирует подграф С, образо- ванный теми вершинами зоны S, которые достижимы в графе G из вершины р0 на путях, не проходящих через вершину р. При этом каждая дуга, исходящая из С, заме- няется на две дуги (по одной для каждого экземпляра С), а все дуги, заходящие извне в вершины подграфа С, распределяются по двум его экземплярам таким образом, что все дуги, принадлежащие зоне S, заходят в один из экземпляров С, а все не принад- лежащие зоне S дуги — в другой. Стандартное преобразование графа G, изображенного на рис. 4.17 (слева), относи- тельно вершины 5 определено и переводит ее в граф, приведенный на рис. 4.18 (справа). Поскольку из максимальной многовходовой зоны {2, 3, 5, 6}, содержащей вершину 5, только вершины 2 и 3 достижимы на путях из р0, не содержащих 5, толь- ко из копии (вершины 9 и 10) и создаются в результате стандартного преобразования относительно 5. А. Любая экономная расклейка графа G может быть получена из него последова- тельностью стандартных преобразований. Б. Любая экономная расклейка п-вершинного графа содержит не более чем 2" 2+1 вершин и требует не более чем 2"-3— 1 применений стандартного преобразования', существует граф, на котором эти оценки достигаются.
Гпава 4. Сводимые и регуляризуемые графы 283 Для любой вершины р уграфа G обозначим через т(р) количество различных много- входовых зон уграфа G, содержащих р, а через Л(р) — минимальное число такое, что имеется множество, состоящее из к(р) вершин и включающее хотя бы по одной вер- шине каждой из тех многовходовых зон уграфа G, которые целиком лежат в макси- мальной многовходовой зоне, содержащей вершину р. В. Существует алгоритм, который эквивалентными дублированиями преобразует любой уграф G в такой регуляризуемый уграф, в котором имеется не более чем 2,ni"("'(/’)-*(Л)} экземпляров любой вершины р уграфа G Следует отметить, что большинство современных языков высокого уровня являются языками структурного программирования и, таким образом, ориентированными на написание регуляризуемых программ. Для языков программирования, таких как Фортран, исследования характеристик реальных Фортран-программ, проведенные Д. Кнутом, показывают, что 90% уграфов регуляризуемы, причем в среднем /(G)» 2,75, а зоны занимают небольшую часть программы (около 4%). Отсюда сле- дует, что в реальных случаях даже для языков "неструктурного” программирования, как правило, уграф регуляризуем, а если нет, то его регуляризация не потребует даже двукратного увеличения размера при сохранении времени счета по программе. 4.2. Разрушение контуров в сводимых графах Задача разрушения (разрезания) всех контуров в орграфе состоит в нахождении ми- нимального множества дуг, удаление которых делает граф бесконтурным. Эта задача важна при исследовании больших систем с обратными связями. Наиболее часто встречающийся подход к анализу таких систем состоит в моделировании структуры системы орграфом и превращении системы в систему без обратных связей путем удаления наименьшего по мощности множества дуг, после чего система может быть проанализирована стандартными методами. Потом удаленные обратные дуги восста- навливаются и система вновь подвергается анализу итеративным способом. Эмпири- чески замечено, что сходимость итерационного процесса много быстрее, если мощ- ность множества удаляемых дуг минимальна. 4.2.1. Постановка задачи Известно, что задача нахождения минимального множества обратных дуг в орграфе WP-трудна. Также NP-трудна близкая задача нахождения минимального разрываю- щего множества вершин, т. е. такого множества вершин, удаление которых разрывает все обратные пути. Однако обе эти задачи решаются за полиномиальное время для класса сводимых графов. Эти задачи тесно связаны между собой в том смысле, что существуют методы сведения одной задачи к другой, которые сохраняют замкну- тость приближенных решений, если будет найден для любой из задач хороший при- ближенный алгоритм. Однако сведение задачи о дугах к задаче о вершинах не сохра- няет свойства сводимости графа и, следовательно, это сведение не может быть ис-
284 Часть I. Обработка и визуализация графов пользовано вместе с методом решения задачи о вершинах для эффективного нахож- дения множества обратных дуг. Рассмотрим полиномиальный алгоритм для нахождения минимального множества обратных дуг в сводимом графе. Более того, предлагаемый алгоритм применим к сводимым графам с взвешенными дугами, для которых отыскивается множество об- ратных дуг с суммарным минимальным весом. Алгоритм представляет собой много- кратное применение алгоритма для нахождения максимального потока в специаль- ной сети, построенной из исходного сводимого графа. Трудоемкость описываемого алгоритма равна O(mn2 \og(n2/my), где п— число вершин, а т— число дуг в исход- ном графе. Эта трудоемкость равна по крайней мере трудоемкости нахождения ми- нимального разреза в сети того же самого размера (для которого самый быстрый из известных к настоящему моменту алгоритмов имеет трудоемкость ®(/ля log(«2/«z))). Для обычных, т. е. невзвешенных, сводимых графов предлагаемый алгоритм находит минимальное множество обратных дуг за время O(min(№, тп513)) и эта трудоемкость равна по крайней мере трудоемкости нахождения минимального разреза в сети с единичными пропускными способностями, для чего известен алгоритм с трудоем- костью ®(тш(«ш2/3, ш3/2)). Предлагаемый алгоритм адаптируется также к задаче нахождения разрывающего множества вершин с минимальным суммарным весом в графе с взвешенными вер- шинами. Это важно, т. к. вес вершины может определять желательность ее включе- ния в разрывающее множество. 4.2.2. Необходимые определения Пусть G = (К, Л, г) — управляющий граф с начальной вершиной г. Граф G называется взвешенным, если каждой его дуге (вершине) сопоставлено вещественное число — вес дуги (вершины). Поскольку графы, рассматриваемые ниже, имеют либо взвешен- ные дуги, либо взвешенные вершины, то из контекста будет всегда ясно, о каком ти- пе взвешенного графа идет речь. Напомним, что (потоковой) сетью G = (Г, A, s, I, С) называется орграф с взвешен- ными дугами с множеством вершин V и множеством дуг А, где 5 и t— вершины из V, называемые источником и стоком соответственно, а С есть функция пропускной спо- собности, специфицирующая неотрицательные веса с(е) дуг. Потоком f по сети G называется функция/ определенная на множестве дуг и удовлетворяющая условиям: О </(е) < с(е), е G А; = ^f(v,y), v*s,t. хеГ уеГ Величина уеК хеИ называется величиной (мощностью) потока f Задача о наибольшем потоке состоит в отыскании для данной сети потока наибольшей мощности. Известно, что величина
Гпава 4. Сводимые и регуляризуемые графы 285 наибольшего потока равна пропускной способности минимального разреза, отде- ляющего s от t. Без ограничения общности будем считать, что веса всех дуг в взвешенном уграфе неотрицательны. Предположим, что в исходном уграфе в корень г заходит хотя бы одна дуга назад; в случае необходимости вводится фиктивная дуга (v, г) с нулевым весом и с произвольной начальной вершиной. Считаем, что вершины в G занумеро- ваны в постфиксном порядке (относительно поиска в глубину с началом в корне г). Пусть G = (И, А, г) — сводимый уграф и K(G) — его каркас — уграф, получаемый из G удалением всех дуг назад. Известно, что K(G) для сводимого графа определяется однозначно. Пусть b = (w, v)~ дуга назад в G. Говорят, что b покрывает вершину w (или w находится под 6), если в K(G) найдется путь из v в и, проходящий через м>. А. Пусть b\ = (wj, Vj) it b2 = (u2, v2) — две дуги назад в сводимом графе G, покрываю- щие общую вершину w. Тогда либо v( доминирует над v2, либо v2 доминирует над vj: если V] > v2 в постфиксном порядке, то тогда vj доминирует над v2, в противном случае v2 доминирует над vb Б. Пусть G = (Т, А, г) — сводимый граф и пусть Ь = (и, v) — дуга назад в G. Тогда v доминирует над каждой вершиной w под Ь. Отношение доминирования удобно представлять так называемым доминаторным деревом Т. Дерево Т — это корневое ордерево с корнем г, в котором потомками вер- шины v являются вершины, доминируемые вершиной v в G. Говорят, что вершина v' непосредственно доминируется вершиной v, если она является сыном вершины v в Т. Доминаторное дерево для G может быть построено за линейное время (см. алгоритм, представленный в разд. /0.3). Отношение доминирования, ограниченное на подмножество вершин V' £ V, пред- ставляется доминаторным лесом Fy. Пусть К/, = { V G V: v есть конец дуги назад в G}. Так как корень г есть конец хотя бы одной дуги назад в G, то очевидно, что /у* есть дерево; это дерево называется кон- цевым доминаторным деревом графа G и обозначаемое Th. Это дерево легко может быть построено из доминаторного дерева Т путем применения преобразования Т2 (см. разд. 4.1.10) к каждой вершине v в Т, которая не является концом дуги назад в G. Пусть G= (К, А, г) — сводимый граф с взвешенными дугами и пусть v— конец дуги назад в G. Пусть bt = (wb v,),..., bl - (ut, v,) — дуги назад в G, концы которых домини- руются вершиной v. Назовем множеством вершин, доминируемых дугами назад, вершины v множество Vv = {v' G V : v' лежит на пути в K(G) из v в некоторую w„ i~ 1,..., z}. Нетрудно заметить, что v доминирует над всеми вершинами из У„. Ь2.3. Потоковая сеть для G Пусть G = (Г, А, г) — сводимый граф с взвешенными дугами (веса неотрицательны) и пусть v— конец дуги назад в G. Тогда G4(rv) = (Иу, А,) есть подграф графа G, порож- денный множеством вершин, доминируемых дугами назад, вершины v. Максималь-
286 Часть I. Обработка и визуализация графов ной потоковой сетью для G относительно вершины v есть потоковая сеть G„,(v), об- разуемая путем расщепления каждой концевой вершины h в Gy(v„) на две вершины h и Л'(рис. 4.19). Рис. 4.19. Пример графа и его максимальной потоковой сети Все дуги в K(G), заходящие в или исходящие из исходной концевой вершины h, бу- дут теперь входить в или исходить из вновь сформированной вершины Л; все дуги назад, входящие в исходную вершину h, будут теперь входить в h'. Из вершины /г'в/
Глава 4. Сводимые и регуляризуемые графы 287 будет теперь вести дуга с бесконечно большой пропускной способностью. Для всех остальных дуг в качестве их пропускных способностей берутся веса этих дуг в G. Мы будем рассматривать v как источник, a t как сток сети G,„(v). Заметим, что множество дуг графа СЛ(И„) есть в точности множество дуг с конечной пропускной способностью в G„,(v). А. Пусть G = (И, А, г) — сводимый граф и пусть Fлюбое множество дуг назад в G. Тогда F отделяет v, от v’ в Gm(v,) для каждой дуги назад b, = (i/„ v,) в G. Обратно, всякое множество дуг С, которое отделяет v, от v', в Gm(y^) для каждой дуги назад = (и„ V,), представляет собой множество дуг назад (МДН) в G. Б. Пусть G — сводимый граф с взвешенными дугами и пусть Ь},..., Ь, суть дуги на- зад с общим концом v и v не доминирует ни над одним концом других дуг назад. То- гда каждый разрез конечной пропускной способности, отделяющий v от t в G,„(v), есть МДН для GV(K,,), и каждое МДН F для GV(H,,) есть разрез конечной пропускной способности, отделяющий v от t в G,„(v). В. Пусть G— сводимый граф с взвешенными дугами и пусть v— конец дуги назад в G Тогда любой разрез конечной пропускной способности, отделяющий v от t в Gm(v), разрывает все контуры, проходящие через v в G„( ИД Пусть G = (V, А, г) — сводимый граф с взвешенными дугами. Определим сеть G,„„,(v) для наибольшего потока минимальной стоимости относительно концевой вершины v следующим образом: □ если v не доминирует ни над одной другой концевой вершиной в G, то G,„,„(v) = G,„(v); Рис. 4.20. Пример сети Gm,„(iz)
288 Часть I. Обработка и визуализация графов □ пусть V],vr— концевые вершины, непосредственно доминируемые вершиной v в G, и пусть пропускная способность минимального разреза в G,„m(y,) равна с„ / = 1,г. Тогда G„m(v) = (И, А), где К есть то же множество вершин, что и в G,„(v), а А = {дуги в G,„(v)} U {дуги в Gmm(vj), /= 1,..., г} U Fv, где Fv = {У™ - (v,v,) : J = 1, ..., г, с пропускной способностью F , равной с} Назовем F,. множеством дуг минимальной стоимости для концевой вершины v; если j есть концевая вершина, непосредственно доминируемая концевой вершиной i, то есть дуга минимальной стоимости из i в j. На рис. 4.20 представлен пример сети Gm„,(v). Г. Пусть G — сводимый граф, в котором V является концом дуги назад, и пусть концевые вершины, непосредственно доминируемые вершиной v в G. суть V|, ...,vr Тогда для i * j множество дуг Gmm(y^) и множество дуг G„„„(v,) попарно различны и, аналогично, множество дуг GV(KV ) и множество дуг Gf(Vv ) попарно различны. I 4.2.4. Определение мощности минимального множества разрывающих дуг Рассматриваемый алгоритм определяет мощность минимального множества дуг, уда- ление которого разрушает все контуры в сводимом графе. Алгоритм 4.4. Мощность минимального разрывающего множества Дано. Сводимый граф G = (К, А, г}. Требуется. Мощность минимального разрывающего множества FAS. Метод. проц МОЩНОСТЬ^ граф) = 1. Занумеровать концы дуг назад графа G в постфиксном порядке; 2. Образовать концевое доминаторное дерево Тк, 3 Ввести в Th указатель из каждой вершины /, / # г, к ее отцу hi, 4. Положить h равным числу концов дуг назад; 5. для i~ 1,.... h цикл 6. % обработка /-й концевой вершины % 7. Найти величину с, минимального разреза в Gm(/); 8 если i # h то 9. Включить дугу с весом с, из hi в / в графе G; все % Заметим, что G изменяется во время работы алгоритма, так что Gm(0 есть тот же самый граф, что и Gmm(/), если G не изменялся % все; 10. ch есть мощность минимального разрывающего множества дуг для G; все
Глава 4. Сводимые и регуляризуемые графы 289 Будем называть дуги, добавляемые на шаге 9, вновь добавленными дугами. Рассмотрим реализацию алгоритма. Считаем, что на шаге 7 сыновьями концевой вершины i в дереве Th будут вершины ц,..., Пусть Fj,..., Fj— максимальные потоки на сетях G„,(zi),Gm(ir), соответственно, которые строятся во время работы алгоритма. Во время исполнения z-й итерации цикла 5—7 эти потоки расширяются до допустимого потока F на сети G,„(z), насыщая вновь добавленные дуги из i в ij,J = 1,..., г. После этого мы находим максимальный поток F, на G,„(z), последовательно находя увеличивающие поток цепи из i в / и посы- лая по ним дополнительные потоки. По окончании этого процесса мы получаем мак- симальный поток и минимальный разрез в Gm(z). Увеличивающие поток цепи строятся как кратчайшие пути в графе, полученном по- сле появления вновь добавленных дуг с весом п (п — число вершин в графе G). Ис- ходные дуги из G и дуги, ведущие в t, берутся с весом 1 (вес дуги не изменяется, проходится ли она в цепи в направлении ее ориентации или против). Можно пока- зать, что всякая увеличивающая поток цепь, построенная таким способом, будет со- держать только дуги с весом 1. Таким образом, каждую такую цепь можно найти ме- тодом поиска в ширину в графе без вновь добавленных дуг. Таким образом, каждая увеличивающая поток цепь может быть найдена за время О(т), где т— число дуг в С. Следовательно, трудоемкость этого алгоритма равна О(т2). Используя алгоритм Диница построения потока в сети с единичными пропускными способностями дуг для графа без вновь добавленных дуг, получаем для алгоритма трудоемкость О(ти5/3), что и дает в итоге оценку O(min(m2, тпп)). 4.2.5. Нахождение минимального множества вершин, разрезающего циклы Алгоритм, рассмотренный в разд. 4.2.4, может быть использован для нахождения в сводимом графе с взвешенными вершинами множества вершин, удаление которых разрывает все контуры и суммарный вес которых минимален Для этого используем сведение задачи об удалении вершин к изученной задаче об удалении дуг с сохране- нием свойства сводимости уграфа. Пусть G = (V,A,r)— сводимый уграф с взвешенными вершинами. Расщепим каж- дую вершину v G V на две вершины vin и voul. Все дуги, входившие ранее в v. стано- вятся дугами, входящими в vm, а дуги, выходившие из v, становятся дугами, выходя- щими из vout. Введем в граф дугу, ведущую из г|п в vout с весом, равным 1, и припишем тот же самый вес всем дугам, заходящим в vjn (рис. 4.21). Обозначим полученный таким образом граф через G'. Легко убедиться, что любое разрывающее множество дуг в G' приводит к разрывающему множеству вершин в G с тем же самым суммар- ным весом. Верно и обратное утверждение. Ясно, что G' есть сводимый уграф с кор- нем гт. Вначале данную потоковую сеть G = (И, A, s, t, Q мы превратим за линейное время вбесконтурную сеть G/= (П/, А/, s, t, Q такую, что любой минимальный разрез в ней может быть преобразован за линейное время в минимальный разрез для G. Пусть 10 Зак. 202
290 Часть I. Обработка и визуализация графов Рис. 4.21. Расщепление каждой вершины ve V исходного графа на две вершины virl и vOut Рис. 4.22. Пример редукции графа
Глава 4. Сводимые и регуляризуемые графы 291 со— минимальная пропускная способность любой дуги в Gy; Образуем сводимый уграф с взвешенными вершинами G' = (I7', A', s) объединением вершин 5 и / в С( и приписыванием веса пс0 каждой вершине в v, где п = |И]. Заменим каждую дугу о -(гг, v) в А] двумя дугами а, = (u, у„) и а2 = (Ч» v), введя новую вершину va с весом С(а). Легко убедиться, что любое минимальное разрывающее множество вершин для Сбудет состоять только из вновь введенных вершин, а дуги в Gy, которым они соот- ветствуют, образуют минимальный разрез для Gt. На рис. 4.22 приведен пример та- кой редукции. 4.2.6. Приближенный алгоритм нахождения множества разрывающих дуг В этом разделе мы изложим быстрый и эффективный эвристический алгоритм оты- скания множества разрывающих дуг для произвольного орграфа. Предположим, что вершины орграфа G расположены в некотором порядке на гори- зонтальной оси и занумерованы слева направо vb v2, —> v„. Назовем такое упорядоче- ние вершинной последовательностью и обозначим ее 5 = V|V2 ...у„. Каждая вершинная последовательность 5 порождает множество R(s) разрывающих дуг, состоящее из всех ориентированных налево дуг(у;,Ч), j > /; более того, каждое множество разры- вающих дуг соответствует некоторой вершинной последовательности. Таким обра- зом, задача о множестве разрывающих дуг эквивалентна задаче отыскания вершин- ной последовательности s’, для которой /?(s*)=7?*(G). Описываемый "жадный" алгоритм GR вычисляет "хорошую" вершинную последова- тельность S, т. е. последовательность с "небольшим" множеством R(s). Этот алгоритм удаляет из графа G вершины (и инцидентные им дуги), которые либо являются сто- ками или источниками, а затем удаляет вершину и, для которой величина 8(zz) = = d\u) - d (w), где сГ(м) — полустепень исхода, а сГ(и) — полустепень захода верши- ны и, наибольшая в данный текущий момент. Если удаленная из G вершина и есть сток, то она присоединяется к вершинной последовательности з2; в противном случае «присоединяется к последовательности Когда G оказывается сведенным к пусто- му графу с помощью последовательных удалений, итоговая вершинная последова- тельность S' получается с помощью конкатенации л = stx2. Алгоритм 4.5. Вершинная последовательность Дано. Граф G. Требуется. Вершинная последовательностьs. Метод. проц GR = 1. S( <- 0; s2 <- 0; 2. пока G * 0 цикл 3. пока G содержит сток цикл 4. Выбрать сток и; s2 := ust, G =G\u; все;
292 Часть I. Обработка и визуализация графов 5. пока G содержит источник цикл 6. Выбрать источник и; 7. Si := Siu; G := G \u; все; 8. если G * 0 то 9. Выбрать вершину и, для которой 5(u) максимальна, 10. Si := Siu; G := G \u; все все; 11. Si := sis2 все Алгоритм 4.5 вычисляет либо пустую вершинную последовательность, либо вер- шинную последовательность s, для которой имеет место оценка |/?(s)| < т/2 - п/6. Б. Если G — турнир, то алгоритм GR вычисляет вершинную последовательность S. для которой |fl(s)| < т/2 - [л/2J/2. Рассмотрим реализацию алгоритма GR. Удобно разбить множество вершин исходно- го графа G на источники, стоки и 8-классы следующим образом: Vd = {и G К: d= 8(w); d\u) > 0; сГ(и)> 0}, -п + 3 < d < п - 3; К,и2 = {и G V: d'(и) = 0}; И„_2= {w е V: d~(u) = 0}. Ясно, что каждая вершина и G V попадает в точности в один из этих 2л - 3 классов. Для вычисления этих классов для заданного графа алгоритм GR должен выполнять в качестве начального шага "ящичную" сортировку (bin sort). Вершины каждого класса связываются друг с другом двунаправленным списком. Эта структура требует для построения О(т) времени и О(т) памяти. Используя ящики, становится тривиальным распознавать сток, источник или верши- ну и, для которой величина б(л) — наибольшая. Более того, имея определенную вер- шину и, становится также тривиальным вычисление ж, и s2 и выявление одновремен- но направленных влево дуг, инцидентных и, если таковые существуют. Остается показать, как формируется G\u. Сама вершина и может быть удалена за время 0(1) вычеркиванием ее из списка ее ящика. В результате каждая вершина г, смежная с и, превратится либо в сток, либо в источник, либо в элемент смежного ящика. Реализация этих изменений требует 0(1) времени на каждую дугу, инцидент- ную и.
Глава 4. Сводимые и регуляризуемые графы 293 4.2.7. Алгоритм Бергера — Шора Данный алгоритм относится к 2-приближенным алгоритмам, т. е. к алгоритмам, га- рантирующим не более чем двукратное отклонение от оптимума. Вообще существу- ют два подхода к решению задачи, гарантирующих указанное отклонение от опти- мума в худшем случае даже в случае, когда в графе нет контуров длины 2. Для удоб- ства описания будем говорить о построении приближенного бесконтурного орграфа с наибольшим числом дуг. Первый подход использует "жадную" стратегию для включения дуг в приближенный бесконтурный орграф. Алгоритм создает два множества S и Т. Он "жадно" перебира- ет все дуги исходного графа G = (И, Л), добавляя дугу в множество S, если ее добав- ление оставляет граф Gs = (Е, S) бесконтурным, в противном случае дуга добавляется вТ. Когда все дуги просмотрены, наибольшее из множеств S или Тберется в качестве аппроксимирующего бесконтурного орграфа. Легко показать, что если G.S = (K, S) — бесконтурный, то и Gr=(V,T)— также бесконтурный. Заметим, что существуют графы и порядки выбора дуг, для которых |5| = |7] Второй подход состоит в размещении вершины исходного графа G = (К, Л) в некото- ром порядке слева направо на числовой оси и добавлении дуги. Дуги, идущие слева направо, помещаются в множество S, а идущие справа налево помещаются в Т Наи- большее из этих множеств берется в качестве приближенного бесконтурного графа. Очевидно, что ни G\ = (Е, S), ни G-/ = (И, Т) не содержат контуров. Как и выше, здесь тоже может быть |S| = |7]. Рассмотрим теперь собственно алгоритм /1(G), принадлежащий Бергеру и Шору. Этот алгоритм просматривает в некотором порядке вершины графа и, если вершина имеет больше входящих дуг, чем выходящих, входящие дуги удаляются из графа и заносятся в множество А ; выходящие дуги удаляются и отбрасываются. Если же выходящих дуг по крайней мере столько же, сколько и входящих, то мы добавляем выходящие дуги к А , а входящие отбрасываем. После просмотра всех вершин мно- жество А, где |Л[ >у \А\, дает искомое решение. Трудоемкость алгоритма— О(п + гп). Заметим, что A(G) может отбросить дугу, не принадлежащую никакому контуру. Чтобы предотвратить это, можно добавить еще один шаг перед обработкой вершин графа G. Во время этого шага перебираются все бикомпоненты в графе и к множест- ву А относят все дуги, которые соединяют разные бикомпоненты. Этот шаг увели- чивает трудоемкость алгоритма до G(hot). Рассмотрим теперь алгоритм 7?(G) с трудоемкостью О(п + т) для нахождения множе- ства А такого, что | Л | > (1/2 + Q(1/-Ja(G) ))И|. Этот алгоритм является уточнением алгоритма A(G) в том смысле, что вместо произ- вольного порядка обработки вершин в процессе исполнения алгоритма вершины вначале упорядочиваются, а затем обрабатываются в этом порядке. Рассмотрим вна- чале разницу между числом дуг, отнесенных к А, и числом отброшенных дуг при обработке вершины v. Эта разница может быть смоделирована маршрутом длины
294 Часть I. Обработка и визуализация графов d(y) + сГ(у) из |бГ(у) - <Z'(v)| в 0, где каждый раз обрабатывается сосед вершины у, причем выбирается шаг+1 или -1. Направление каждого единичного шага по мар- шруту определяется тем, является ли соответствующая смежная с обрабатываемой вершина концом или началом дуги, инцидентной у. Заметим, что вершина не может быть одновременно и концом, и началом дуги, инцидентной v, т. к. граф не содержит контуров длины 2. Длина маршрута равна сГ(у) + йГ(у), т. к. таково число соседей у у. Значение маршрута в момент, когда обрабатывается вершина у, равно разности меж- ду числом дуг, занесенным в А , и числом отброшенных дуг. Этот маршрут фактиче- ски является случайным маршрутом, т. к. соседние вершины обрабатываются в про- извольном порядке. Эквивалентно, мы будем смотреть на маршрут как на обратный, если он начинается в 0 |сГ(у) - </(v)|. Рассмотрим теперь случайный маршрут поближе. Пусть ш(/) — значение маршрутам после i шагов. Тогда и’(0) = 0 и w(d) = t, где d— длина маршрута, a t— его конец. Таким образом, d= d(y) + d(y) и /=|сГ(у) -tT(v)|. Алгоритм R(G) выбирает едино- образно из всех маршрутов маршруты с шагами +1, длиной d. началом в 0 и концом в Т. Так как маршрут определяется исключительно позициями +1 и -1, то каждый маршрут генерируется точно d~(y)\cT(y)\ Перестановками соседей V. Следовательно, алгоритм R(G) порождает каждый маршрут с одной и той же вероятностью. Из при- водимых рассуждений следует, что когда обрабатывается вершина у, ожидаемая раз- ность между чисом дуг, занесенными в А , и числом отброшенных дуг равно Q(Vrf) Используя данные результаты, можно построить полиномиальный детерминирован- ный алгоритм для нахождения максимального бесконтурного подграфа, который для данного орграфа G = (И, А) находит множество А такое, что | Л |>(1/2 +Q(l/7A(G) ))И|. Определим алгоритм D(G), который на входе имеет граф G = (Г, А) без контуров длины 2, а на выходе — множество А . Пусть £(| А |) — ожидаемая мощность множе- ства А, порождаемого алгоритмом R(G). Пусть procd(yb ...,у*) означает, что вершины уь —, у* уже обработаны в том порядке, в котором они перечислены. Алгоритм 4.6 Дано. Граф G = (Г, А) без контуров длины 2. Требуется. Множество А. Метод. для i от 1 до | V] цикл 1. На /-й итерации этого цикла будем предполагать, что вершины, обозначенные через уц уже обработаны и именно в таком порядке. 2. Выбрать вершину v е V\{vi,.... v<-i}. для которой Е(| А 11 procd(vi, .... ум, v)) максимальна. 3. Пометить вершину v как у,-. все
Глава 4. Сводимые и регуляризуемые графы 295 Покажем теперь, как можно вычислить Е(| А | | procd(vb v,_b v)). Мы знаем, как много дуг от всех обработанных вершин попали в А. Для необработанных вершин мы можем вычислить точное число дуг, которые будут добавлены к А , с помощью определенного выше случайного маршрута. Пусть р(Л, v) — число дуг, добавляе- мых к А при обработке v. Тогда Е(| А 11 procd(V|, ..., v,_b v)) = = XpCAv") + Procd(vi, v,-i, v)). v*g(V|, .... г,.,, i’} Первая сумма вычисляется легко. Вторую вычисляем следующим образом. Пусть v' имеет c/(v') выходящих дуг, ведущих в И\{уь ..., v,_b v}, и сГ(уг) входящих дуг, начи- нающихся в К \{vb ..., v,_b v}. Заметим, что мы теперь используем d(y') и d~(vr) для обозначения полустепени исхода и полустепени захода вершины v' относительно подграфа графа G, индуцированного множеством вершин E\{vb . , Vj_b v}, а не отно- сительно исходного графа G. Пусть d(v') — d'(yr) + cT(v') и t(vr) = \сГ(v') - cT(v')|. Пусть w— случайный маршрут из 0 в r(v'), имеющий d(v’) шагов, иг— переменная, при- нимающая с равной вероятностью значения от 0 до d(yr) независимо от w. Пусть, на- конец, / = w(r) — случайная переменная, значение которой равно длине маршрута w как функции от г. В принятых обозначениях имеем (выкладки опущены) E(p(A,vr) | procd(vb .v,_b v))=-^p-+— Мы можем теперь вычислить Е(| 1.11 и’(с/) = г), используя равенство £(1/11(60=0=- / + £(|/||w(e/-l) = r-l) + ^2£(|/||w(J-l) = z + l) Так как это математическое ожидание зависит исключительно от значений d и t, вначале алгоритма мы можем построить таблицу table! 1 такую, что tabIeIl[c/,Z]<-E(|/||w(c/) = O для всех 0 < t < d < A(G). Хотя эта таблица будет использована для просмотра ожи- даемых значений для различных значений d и / во время исполнения алгоритма, эле- менты таблицы, соответствующие данным значениям J и t, никогда не изменяются. 4.2.8. Алгоритм Шамира Пусть заданы управляющий граф G = (X, U,po) и обратная нумерация его вершин N. Определим функцию ВЕРХ, которая каждой вершине реХ сопоставляет число ВЕРХ(р), 0 < ВЕРХ(р) < п, удовлетворяющее следующему условию: ВЕРХ (р) = max(0, {N(q) : q е X(p)}).
296 Часть I. Обработка и визуализация графов Здесь К(р) обозначает множество всех таких вершин q е X, что существует путь P = (Pi=P,P2, ...,pr-l,pr=q\ для которого справедливы следующие два условия: □ /V(p,-i) < N(Pi) * ВЕРХ (/?,) для всех i таких, что 1 < i < г; □ Nipr-t) > N(pr). Рассмотрим уграф, изображенный на рис. 4.23. Вершины уграфа помечены своими TV-номерами, а значения функции ВЕРХ задаются рядом с соответствующими верши- нами. Рис. 4.23. Функция ВЕРХ для сводимого уграфа Рис. 4.24. Функция ВЕРХ для несводимого уграфа А. Если существует в уграфе G вершина р, для которой ВЕРХ(р) > Л(р), то G не является сводимым. Это условие является достаточным условием несводимости уграфа, но не является необходимым, что демонстрируется графом G, представленным на рис. 4.24. G не является сводимым уграфом, поскольку зона {4,7} имеет две входные вершины, но для любой вершины р выполняется N(p) > ВЕРХ (/?). Обозначим через S множество всех тех вершин р е X, для которых ВЕРХ (/?) = Л'(р). Б. Если для любой вершины р графа G выполняется ВЕРХ (р) < N(p), то S является минимальным разрезающим контуры множеством.
Гпава 4. Сводимые и регуляризуемые графы 297 Алгоритм 4.7. Минимальное разрезающее контуры множество Дано. Граф G. Требуется. Либо минимальное разрезающее контуры множество для G, либо ука- зание на несводимость G. Метод. Алгоритм состоит из двух частей, первая из которых осуществляет обрат- ную нумерацию N вершин графа G, а вторая приведена ниже. функРАЗРЕЗ = 1. S: шкала = (О'7); 2. ВЕРХ : разметка = {(р,0): р е X}; 3. для к от п до 1 через — 1 цикл 4. р := ЛГ1(к); 5. для всех q из ПРЕЕМ(р) цикл 6. если A/(q) < Л/(р) то 7. ВЕРХ (р) := max(A/(q), ВЕРХ (р)) 8. иначе если (ВЕРХ (р) * A/(q) л (S[q] = 0) то 9. ВЕРХ (р) := тах( ВЕРХ (р), ВЕРХ (q)) все все все; 10. если ВЕРХ (р) = Л/(р) то А[р] := 1 11. иначе если ВЕРХ (р) > Л/(р) то 12. возврат G — несводимый уграф все все все; 13. возврат S все Нетрудно проверить, что вторая часть алгоритма обрабатывает каждую дугу графа (операторы 5—9) только раз, и таким образом, О(т) — ее временная сложность, где т— число дуг уграфа G. Поскольку обратная нумерация N графа G может быть осуществлена за время О(т), алгоритм 4.6 для нахождения минимального разрезаю- щего контуры множества для сводимого уграфа G требует О(т) времени. 4.3. Анализ циклической структуры и циклически сводимые графы Хорошо известно, что время выполнения любой программы в значительной мере за- висит от времени выполнения ее самых внутренних циклов. Поэтому анализ цикли- ческой структуры программ представляется весьма важным во многих приложениях. Существует достаточно большая группа алгоритмов, которая непосредственно ори- ентируется на циклическую структуру обрабатываемой программы.
298 Часть I. Обработка и визуализация графов 4.3.1. Понятие цикла в уграфе Первый вопрос, который возникает при оптимизации программ с циклами, представ- ленных в виде графов, — что такое цикл в уграфе (или, что то же самое, какой тип фрагмента уграфа формализует понятие цикла в программе). С точки зрения оптимизации, выделяются следующие два характерных свойства цик- ла— фрагмента уграфа, представляющего цикл программы. Во-первых, цикл являет- ся участком многократного выполнения, т. е. вершины и дуги цикла образуют зону. Во-вторых, цикл — это участок повторяемости. Другими словами, для любой цепоч- ки выполнения программы, представляющей собой некоторый путь от начальной вершины графа, количество вхождений в нее дуг, заходящих извне в цикл, не пре- вышает числа вхождений в цепочку инцидентной им начальной вершины цикла, а суммарное число вхождений начальных вершин цикла во все пути графа от его на- чальной вершины существенно превышает количество всех вхождений дуг, иниции- рующих цикл. Ниже рассматриваются две основные задачи, связанные с анализом циклической структуры графа: оценка частоты выполнения операторов и переходов в графе и вы- явление иерархии циклов в нем. 4.3.2. Достоверные частотные отношения Пусть задан некоторый уграф G с начальной вершиной р0 и конечной вершиной ц0. Обозначим через N множество путей по G от р0 до с/0, а через |Р гл М\\ — количество вхождений элементов из М\ с М в некоторый путь Р по графу. Здесь и ниже М обо- значает множество вершин и дуг графа G. Пусть Mt и М2 — два элемента из 2м. Будем говорить, что Л/, и М2 достоверно вы- полняются одинаково часто в G (обозначаем М}=М2), если для любого Р из вы- полняется \Мх гл = |Л/2 о Р|. Элемент Л/, достоверно выполняется "чаще", чем Мг (обозначим Mi <-М2), если |Л/( гл Р| < |Л/2 гл для любого пути Р е N и существует такой путь Р е N, что |Л/( гл Р| < |Л/2 о Р|. Заметим, что достоверные частотные отношения играют весьма важную роль при решении задачи оптимизации программы. Целесообразность (оптимизационный эф- фект) ни одного из оптимизирующих преобразований нельзя гарантировать, если не обеспечены определенные достоверные соотношения частот выполнения между эле- ментами преобразуемого фрагмента. Обозначим через V множество всех простых путей графа G, принадлежащих N, а че- рез W— множество всех его контуров. Элементы множества E=¥y)W будем назы- вать цепочками уграфа G: простыми, если они принадлежат V, й замкнутыми, если они содержатся в W. А. Для любых подмножеств Мх и М2 из М выполняются следующие два свойства: Mt <-М2 тогда и только тогда, когда |Л/, гл Р| < |Л/2 гл Р| для любой цепочки РизЕ и существует такая цепочка Р в Е, что \М\ гх Р\ < \М2 ГЛ Л*]; Mi = М2 тогда и только тогда, когда \М{ гл Р| = |Л/2 гл Р| для всех цепочек Р из Е.
Глава 4. Сводимые и регуляризуемые графы 299 Данное свойство позволяет осуществить нахождение отношений частот без рассмот- рения бесконечного множества N путей по G. Однако и такой способ во многих си- туациях оказывается неэффективным, поскольку для каждой пары подмножеств Мх и М2 множества М он требует рассмотрения множества Е. Более эффективным кажется подход, суть которого состоит в следующем. Граф представляется в виде иерархии вложенных участков многократного выполнения специального вида, а каждому под- множеству М\ с М сопоставляется вектор частот таким образом, что выполняются следующие три свойства: □ элементы вектора частот, сопоставленного некоторому Мх с М, — это оценки частоты выполнения М\ на участках многократного выполнения всех возможных уровней вложенности; П вектор частот любого Мх с М получается суммированием соответствующих эле- ментов векторов частот всех элементов из Му, П для любых М\, М2 <z. М отношения между соответствующими элементами векто- ров частот М\ и М2 не противоречат друг другу и отношениям достоверных частот выполнения Мх и М2. Ниже рассматривается реализация этого подхода для участков повторяемости графа общего вида и для циклических участков сводимых графов. 4.3.3. Участки повторяемости Понятно, что элемент (вершина или дуга) графа G может входить более одного раза в некоторую цепочку выполнения программы, представленной графом G, тогда и только тогда, когда он принадлежит некоторой замкнутой цепочке графа G. Таким образом, множество простых цепочек V образует его участок повторяемости уровня нуль, а участки повторяемости уровней i, i > 1, образуются подмножествами замкну- тых цепочек. При этом в общем случае можно утверждать, что замкнутая цепочка Рх вложена в замкнутую цепочку Р2 (или, что то же самое, степень повторяемости це- почки Pt выше, чем степень повторяемости цепочки Р2~) только в том случае, когда Р2 содержит все вершины и все дуги цепочки Рх за исключением одной дуги. Действи- тельно, для графа G, изображенного на рис. 4.25, нельзя утверждать, что какая-то одна из двух замкнутых цепочек графа выполняется чаще второй. Будем говорить, что замкнутая цепочка Рх непосредственно вложена в замкнутую цепочку Р2, если Р} вложена в Р2 и не существует такой замкнутой цепочки Р2, что Рх вложена в Р2, а Р2 вложена в Р2. Цепочка Р е W называется внешней, если в ГК не су- ществует такой цепочки, в которую Р вложена. Множество цепочек С назовем зацепленным, если оно состоит из попарно не вло- женных замкнутых цепочек и граф, образованный всеми теми вершинами и дугами, которые принадлежат цепочкам из С, является сильно связным. Пусть С| и С2 — два зацепленных множества замкнутых цепочек графа G; С) (непосредственно) вложено в С2, если пересечение С| и С2 пусто и для любой цепочки из Сх найдется цепочка в С2, в которую она (непосредственно) вложена.
300 Часть I. Обработка и визуализация графов Рис. 4.25. Уграф и его цепочки Участки повторяемости графа G определяются следующим образом: G содержит единственный участок повторяемости уровня нуль, состоящий из всех простых цепо- чек графа G; участки повторяемости первого уровня — это максимальные зацеплен- ные множества внешних замкнутых цепочек; участком повторяемости i-го уровня является каждое максимальное зацепленное множество замкнутых цепочек, непо- средственно вложенных в некоторый участок повторяемости уровня (z—1). Множест- во участков повторяемости графа G уровня i будем обозначать Н,. А. Каждая цепочка графа G принадлежит ровно одному участку повторяемости графа. Б. Пусть Т\ и Т2— два участка повторяемости ненулевого уровня. Тогда либо один из них вложен в другой, либо пусто пересечение любой пары цепочек Pt е Nt и Р2 е Т2. Пусть h — максимальный уровень участков повторяемости графа G. Частоту выпол- нения некоторого подмножества A g М оценим вектором FA = (F1’А, ..., Р°А\ в кото- ром для любого / е [О, И\ имеем ?а = &т ГеН, РеГ
Глава 4. Сводимые и регуляризуемые графы 301 где к/— коэффициент выполнения участка повторяемости Т, определяемый по сле- дующим трем правилам: П если Т е Но, то kT= 1; П если Т е Н\, то kj— число простых цепочек пересекающих замкнутые цепочки участка Т\ П если Т е Н„ i е (1 : h], то кг= кгг, где 7\— участок повторяемости, в который непосредственно вложен Т, а г— число тех замкнутых цепочек из 7\, в которые непосредственно вложены цепочки из Т. В качестве примера рассмотрим граф G, изображенный на рис. 4.25 и содержащий два участка повторяемости 7\ = Ии Т2 = W, для которых кц =кТ1 =1. Вектора частот, приписанные вершинам и дугам графа G, изображены там же, на рис. 4.25, рядом с соответствующими элементами графа G. В. Для любых М\, М2 е 2м выполняются следующие свойства: если Mt = М2, то - F'Mi для любого i е [0, h]; если Mt < М2, то < F^ для любого i е [0, h] и найдется такое j е [0, Л], что F^ < F^ . Следует заметить, что хотя вышеописанный способ оценки частоты выполнения и дает достаточно надежную информацию, тем не менее лучшие из существующих алгоритмов нахождения замкнутых цепочек имеют временную сложность 0((н+т)-(|Wj+1)), a ftP] может достигать величины х сг+1 («-/)!, /=1 где C''~'+I обозначает число сочетаний из п элементов по п - / + 1. Ниже описыва- ется другой способ представления графа в виде вложенности участков многократного выполнения и оценки частоты выполнения элементов из М по отношению к этим участкам. Этот способ ориентируется на сводимые графы, но имеет сложность Офт). 4.3.4. Циклические участки графа Рассмотрим последовательность графов Go = G, Gt,..., Gn в которой только граф Gr не содержит нетривиальных бикомпонент, и для любого / е [1, г] граф G, получается из G,_| удалением в каждой нетривиальной бикомпоненте С графа G,_| всех дуг, заходящих в один из ее входов. Эту входную вершину бикомпоненты С будем называть ее головой, а удаленные дуги — дугами повторения уровня /. Пусть /, обозначает множество всех дуг повторения уровня / е [1, г]. Части графа G, называемые ее циклическими участками, определяются по следую- щим двум правилам: П циклический участок нулевого уровня в графе G один; он состоит из всех тех вершин и дуг, которые принадлежат путям по Gr от р0 к q0, и имеет головой вер- шину р0;
302 Часть I. Обработка и визуализация графов П пусть i е [1, г] и С— бикомпонента графа с головой р; тогда в G имеется циклический участок уровня i с головой р\ он состоит из всех тех вершин и дуг, из которых достижима р на графе, полученном из С удалением всех дуг повторения уровня j > i. Рассмотрим в качестве примера граф G, изображенный на рис. 4.25. В нем дугами повторения являются дуги (4,2) и (5,3), причем (4,2)— дуга повторения первого уровня, а (5,3)— второго. Граф G имеет три циклических участка (см. рис. 4.25): Z0 — нулевого уровня с головой 1, Z1 — первого уровня с головой 2 и Z2 — второго уровня с головой 3. Заметим, что в G два участка повторяемости — И и W. А. Циклические участки и их головы выделяются в графе G однозначно тогда и только тогда, когда G — сводимый граф. Б. Любые два циклических участка одного уровня не содержат общих элементов графа. В. Каждый циклический участок Z графа G образован множеством вершин и дуг некоторого подмножества цепочек E(Z) а Е, причем для любых двух циклических участков Z, и Z2 пусто пересечение множеств E(Z\) и E^Z?). Частота выполнения некоторого подмножества АсМ оценивается вектором Da ={Da ,Da4 ,..., Da), в котором для любого i е [0, г] выполняется £>>Ем Е^ИМ)- ZeR, Rel-(Z) Здесь и ниже используются следующие обозначения: П Я, — множество циклических участков уровня i; □ k2— коэффициент выполнения циклического участка Z, который равен единице, если i = 0, либо равен qeB □ если Z порожден бикомпонентой с множеством начальных вершин В; П кР— коэффициент выполнения цепочки P=(Pt, P2,...,Pj) из E(Z), равный i где Tj— число дуг в Z, исходящих из вершины Рр если Pj * Qo, и единица, J=i если Pj = Qo. Например, для уграфа, изображенного на рис. 4.26, частоты выполнения элементов описываются векторами, указанными рядом с соответствующими элементами. Г. Для любых М\, М2 е Iм выполняются следующие два свойства: 1) если, Mt = М2, то Р'м^ = Р'М1 для любого i е [0, /?]; 2) если < М2, то для любого i е [О, Л] выполняется D'Mi < Р'Мг, причем если G — сводимый граф, то существует такое j е [О, Л], что PlM < D'Mi
Глава 4. Сводимые и регуляризуемые графы 303 Рис. 4.26. Частоты выполнения вершин и дуг сводимого уграфа, найденные на основе выделения циклических участков уграфа Пример графа G, изображенного на рис. 4.27, показывает, что сводимость графа — достаточное, но не необходимое условие того, чтобы отношения векторов частот не противоречили достоверным отношениям частот выполнения. Действительно, если в качестве головы циклического участка Z', порожденного единственной нетривиаль- ной бикомпонентой S графа G, взята вершина 2, то циклические участки выделяются так (см. рис. 4.27), что каждая цепочка графа принадлежит множеству £(Z)uE(Z'). Если же в качестве головы при рассмотрении S взята вершина 3, то для множеств Mi = {(1,2); (2,3); (1,3)} и М2 = {(3,4); (3,2)} получаем ЛД < М2 и DM\ = DM2. Д. Для любого циклического участка Z графа G уровня I выполняются следующие свойства’, если р — голова Z, то D‘p = k7‘, если не пусто множество Y дуг графа Z, заходящих в некоторую вершину р, то D'p =^D'U; если I— число дуг графа Z, исхо- дящих из некоторой вершины ран обозначает любую из этих дуг, то D'p = ID'U. Алгоритм 4.8. Оценка частоты на основе циклических участков Дано. Уграф G. Требуется, Циклические участки уграфа G и векторы частот для всех элементов изМ.
304 Часть I. Обработка и визуализация графов Рис. 4.27. Частоты выполнения вершин и дуг несводимого уграфа, построенные на основе выделения в нем циклических участков Метод. Решение находится в два этапа. На первом этапе с использованием алгоритма /’-нумерации (см. разд. Ю.2.2) за г ша- гов осуществляется построение последовательности уграфов Go =G,Gl,...,Gl., на /-м шаге которого выделяются бикомпоненты в уграфе G,, головы циклических участков уровня i и дуги повторения уровня /. Первый этап завершается выделением всех цик- лических участков уграфа G. На втором этапе обрабатывается каждый циклический участок Z. Процесс обработки Z состоит в том, что сначала с помощью алгоритма базисных нумераций строится Л-нумерация вершин из Z, а затем вершины из Z просматриваются в порядке возрас- тания их /V-номеров, и для каждой просматриваемой вершины р и для всех дуг, исхо- дящих из р, по формулам из свойства 4.3.4, Д вычисляются соответствующие компо- ненты векторов частот. В силу линейной сложности алгоритма /’-нумерации и его очевидной модификации, нацеленной на выделение бикомпонент, их начальных вершин и их дуг, заходящих в эти вершины, сложность первого этапа— О(пп), где г < п. Эта оценка является спра- ведливой и для второго этапа, поскольку в силу свойства 4.3.4, Б сложность обработ- ки всех циклических участков одного уровня составляет О(т). 4.3.5. Циклически сводимые графы Прежде чем определить циклически сводимые графы, введем ряд определений. Для данного графа G = (И, £) и подмножества вершин .S'c Г редукцией G. определяе- мой S (обозначение G -S), называется подграф G' = (И- S, Е'), где Е' = £ - {(х,у):х е G £ или у G £}. Аналогично, если G' = (V, Е1) — подграф графа G, то через G — G' мы будем обозна- чать редукцию G, определяемую V. Будем говорить, что вершина z заперта
Гпава 4. Сводимые и регуляризуемые графы 305 (deadlocked), если в G существует путь из z в некоторую вершину у, лежащую на кон- туре Заметим, что вершина, имеющая петлю, считается лежащей на контуре Заме- тим также, что если z заперта, то должна существовать запертая вершина у (необяза- тельно отличная от z) такая, что существует дуга из z в у. Ассоциированным графом вершины X относительно графа G (обозначение A(G, х)) называется подграф, порожденный вершиной х и всеми вершинами в G, которые ос- таются незапертыми, если х удаляется из G. Ясно, что дугами графа /(G, х) являются те дуги из G, которые инцидентны только вершинам из A(G, х) Пример графа и ассоциированных графов его вершин приведен на рис. 4.28. Ассо- циированный граф называется циклическим, если он содержит хотя бы один контур. Рис. 4.28. Пример графа и ассоциированных графов D-последовательностью графа G называется последовательность вершин (уь ...,у*) такая, что каждый из графов H(G/_|,.y/) является циклическим, где Go = G и G, = Gj_| - A(G,-t, уд для 1 < i <k. Ясно, что если ассоциированные графы вершин в ©-последовательности удаляются (пошагово) из G в том порядке, в котором вершины встречаются в ©-последо- вательности, то каждый из этих ассоциированных графов — циклический, ©-после- довательность называется полной, если граф Gk (определенный выше) не содержит контуров. Заметим, что по определению ассоциированного графа полная ©-после- довательность нормально завершается пустым графом. Единственное обстоятельст- во, при котором Gk не пуст, это то, когда исходный граф G не имеет контуров; в этом случае пустая последовательность является единственной полной ©-последова- тельностью. Орграф G называется циклически сводимым тогда и только тогда, когда существует полная ©-последовательность для G.
306 Часть I. Обработка и визуализация графов Граф, показанный на рис. 4.28, есть циклически сводимый граф. Для него существу- ют только две полные ©-последовательности (a, d) и (d, a). Данное выше определение циклически сводимого графа позволяет установить есте- ственное соответствие между этим определением и задачей нахождения минималь- ного разрывающего множества вершин (Fl'S) для такого графа. Имеет место сле- дующее утверждение. А. Если (yi, ...,Ук) есть полная D-последовательность графа G, то множество {Уь есть минимальное разрывающее множество вершин графа G. Используя это утверждение, можно осуществлять нахождение минимального разры- вающего множества вершин графа G с помощью алгоритма нахождения полной ©-последовательности графа G. 4.3.6. Полные D-последовательности В разд. 4.3.6 было дано определение циклически сводимого графа и было отмечено, что существует соответствие между полными ©-последовательностями и минималь- ными разрывающими множествами вершин. К сожалению, это соответствие не ведет непосредственно к эффективному алгоритму для нахождения минимального разры- вающего множества вершин для циклически сводимых графов. Однако оно намечает некоторые подходы В частности, можно попытаться найти FVS для циклически сво- димого графа G путем нахождения полной ©-последовательности G. Один "метод" для нахождения такой полной ©-последовательности состоит в сле- дующем: разместить вершину х в G так, чтобы A(G, х) было циклическим, и удалить A(G, х) из G. Повторить данную процедуру на уменьшенном графе. Если существует несколько альтернатив для выборах, то выбираем х произвольно. Когда процесс заканчивается, тогда вершины, чьи ассоциированные графы были уда- лены, образуют полную ©-последовательность и, следовательно (по свойству 4.3.5, А), FVS для G. Если же процесс не заканчивается (т. е. если достигнута вершина, где ни одна из ос- тавшихся вершин не имеет циклического ассоциированного графа), то нужно вер- нуться в ближайшую вершину, где было несколько альтернатив для выбора х, и вы- брать другую альтернативу. Из-за этого возврата трудоемкость алгоритма может стать в худшем случае экспоненциальной. Идеально было бы выбирать такую аль- тернативу, которая не приводила бы к возврату Следующее утверждение показыва- ет, как производить такой выбор альтернатив. А. Если G— циклически сводимый граф, имеющий такую вершину х, что A(G,x) — циклический, то существует полная D-последовательность для G, у которой х— первая вершина. Это утверждение показывает, что определение циклически сводимого графа удов- летворяет некоторому аналогу свойства Чёрча— Россера относительно полной ©-последовательности. Для обоснования данного утверждения и исследования свойств ©-последовательностей сформулируем ряд определений и утверждений. Заметим вначале, что если х удаляется из G, то некоторая вершина из A(G, х) должна иметь нулевую полустепень исхода, если только х— не единственная вершина в
Глава 4. Сводимые и регуляризуемые графы 307 A(G,x). На базе этого наблюдения процесс размещения всех вершин в /1(0, х) стано- вится процессом последовательного удаления из G вершин с нулевой полустепенью исхода, пока не останется ни одной такой вершины. В соответствии с этим процессом определим два частных вида редукции графа: /{-редукцию и О-редукцию. R-редукция есть удаление из G всех вершин с нулевой полустепенью исхода. При этом результирующий граф R(G) сам может иметь вершины с нулевой полустепенью исхода. Это приводит к следующему обобщению /{-редукции, допуская тем самым повторное применение ее: □ R'(G) = R(G); □ Rk(G) = £(£bl(G)) для k > 2; □ £"(G) = Rm(G), где m есть наименьшее целое такое, что £'"+1(G) = /{"’(G). Ясно, что редукция G за счет удаления вершины х, не запертой в G, есть просто T(G). D-редукция есть просто удаление вершины х, соответствующее выбору х для включе- ния в FVS. Используя эти две редукции, можно строго определить графы, связанные cD-последовательностью (уь ...,Ук), следующим образом: Gt = Rm(D(Gi-t,y,)), «>0, = G,_, -R°W^by,y). Заметим, что //-последовательность является полной тогда и только тогда, когда R°(Gk) — пустой граф. Будем говорить, что G есть R^-граф тогда и только тогда, когда каждая вершина в G незаперта, или, что эквивалентно, каждая вершина имеет полустепень исхода не меньше 1. Ясно, что для произвольного графа G £”(G) есть /{"-граф. Справедливы следующие свойства. Б. Если G = ( V, Е) есть В^-граф и A(G, х) — циклический, то A(G, х) есть В°°-граф. В. Пусть G = (И, £) — произвольный В^-граф. Еслиzuy — вершины из Vтакие, что оба графа A(G, z) и A(G, у)— циклические и A(G, z) r^AfG, у) х 0, то A(G, z) = = A(G,y). На основании свойства 4.3.6, А можно предложить следующий алгоритм нахождения минимального разрывающего множества для циклически сводимого графа с по- мощью нахождения полной //-последовательности. Алгоритм 4.9. ALGFVS Дано. Циклически сводимый граф G = (К £). Требуется. Минимальное разрывающее множество вершин FVS. Метод. проц ALGFVS = 1. FVS<-0; G<-/T(G);
308 Часть I. Обработка и визуализация графов 2. пока G * 0 цикл 3. Пусть х — такая вершина в G, что A(G, х) — циклический; 4. FVS <- FVS и {х}; G <- G - A(G, х); все все Время работы алгоритма составляет О(| И]2 • |£|). Чтобы убедиться в этом, заметим, что цикл пока имеет самое большее |И| итераций, т. к. на каждой итерации к FFS добавляется по крайней мере одна вершина и, следо- вательно, удаляется из G. Внутри каждой итерации доминирующей операцией является размещение в G вер- шины х так, чтобы A(G, х) был циклическим. Это может быть сделано прямолинейно за время О(| И| |£|). Заметим, кстати, что данный алгоритм может также быть использован для распозна- вания циклически сводимых графов. В частности, когда алгоритм применяется к графу, не являющемуся циклически сво- димым, алгоритм гарантирует достижение состояния, при котором ни одна из остав- шихся вершин не имеет циклического ассоциированного графа. Это следует из опре- деления циклически сводимого графа и свойства 4.3.7, А. Соответственно, если алго- ритм "успешно" завершается (т. е. G становится пустым), то граф имеет полную /^-последовательность и, значит, является циклически сводимым. 4.3.7. Связь со сводимыми графами Как уже говорилось выше, сводимые уграфы образуют другой нетривиальный класс графов, для которого задача FASIFVS решается эффективно. Поэтому возникает во- прос о соотношении этих двух классов. Известно, что сводимым уграф является тогда и только тогда, когда он не содержит запрещенного подграфа — части, гомеоморфной графу, изображенному на рис. 4.9. Что касается характеризации циклически сводимого графа в терминах запрещенных подграфов, то здесь имеет место следующее свойство. А. Не существует характеризации циклически сводимых графов в терминах "запре- щенных" подграфов. Можно показать, что эти классы независимы, но имеют непустое пересечение. Так граф, показанный на рис. 4.28, не является сводимым уграфом, но является цикличе- ски сводимым. В свою очередь, сводимый граф на рис. 4.29 не является циклически сводимым. Поскольку между двумя классами нет отношения включения, естественно задать во- прос: "Можно ли выделить в классе циклически сводимых графов какие-нибудь интересные подклассы?" Такой подкласс действительно существует. Назовем RD-графом любой орграф, который не содержит в качестве части подграф, гомео- морфный графу на рис. 4.31 (запрещенный подграф). Дуги запрещенного подграфа
Гпава 4. Сводимые и регуляризуемые графы 309 соответствуют вершинно-различным простым путям в графе, и все три вершины запрещенного подграфа также различны. Заметим, что определения /?О-графа и сво- димого уграфа отличаются только наличием вершины п0, отличной от вершин за- прещенного подграфа. Эта вершина играет значительную роль в сводимых уграфах, и в силу этого не каждый сводимый уграф есть /Ю-граф. Рис. 4.29. Циклически сводимый несводимый уграф Рис. 4.30. Циклически несводимый сводимый уграф Терминальной компонентой графа G называется компонента сильной связности (би- компонента) в G, у которой нет дуг, ведущих из какой-нибудь вершины этой биком- поненты в вершину вне ее. Б. Любой непустой граф имеет по крайней мере одну терминальную бикомпоненту. Рис. 4.31. Запрещенный подграф для ЯО-графа В. Если G = (К, Е) есть терминальная компонента RD-графа G' и G'есть также К°-граф, то A(G, х) — циклический для некоторой вершины х g V. Из свойства В непосредственно вытекают следующие утверждения. Г. Если непустой RD-граф G' есть также Rc°-гpaф, то A(G', х)— циклический для некоторой вершины X е V’. Д. Каждый RD-граф Сесть циклически сводимый граф.
310 Часть I Обработка и визуализация графов 4.3.8. Алгоритм Шпекенмейера для задачи FVS Пусть G = (V,A) — орграф, в котором требуется найти FES-множество F наименьшей мощности. Предварительно проведем "упрощение" графа G, что позволит снизить трудоемкость решения задачи. Это упрощение проводится по следующей схеме. Алгоритм 4.10. Упрощение уграфа Дано. Орграф G = (V, А). Требуется. Орграфы Gj, ..., Gk и подмножество вершин Fс V. Метод. проц SIMPLIFY = 1. F<-0; 2. пока Существует некоторая вершина v е V, которая может быть "легко" распознаваема как принадлежащая минимальному FVS 3. цикл F «- F ш {v}; G «- G {у} все 4. Разложить G на нетривиальные бикомпоненты Gi, ...,G*; 5. пока Существует некоторая G, и дуга (и,у) е А такая, что каждый контур, содержащий и, проходит через (и, у), или каждый контур, содержащий у, проходит через [и, у) 6. цикл Слить и и у в одну вершину все; все Данный алгоритм ищет Fl'S, ограничиваясь бикомпонентами. Условие пока опера- тора 4 выражает тот факт, что после применения оператора 3 к G либо вершина и имеет полустепень исхода, равную 1, либо вершина v имеет полустепень захода, рав- ную 1. Стягивание вершин и и v в новую вершину w означает, что с исключением (г/, v) все дуги, ранее заходившие в и или v, теперь заходят в w, а дуги, ранее выхо- дившие из и или v, теперь выходят из w. Заметим, что если G содержит дугу (и, v), то стягивание порождает петлю (w, w). Этого можно избежать, если специальным обра- зом реализовать оператор 2—3. Пусть v— некоторая вершина и С— контур в G. Будем говорить, что имеет место Petty, С) тогда и только тогда, когда v лежит на С, а все вершины и на С не принадле- жат ни одному контуру в G\{v). Наконец, мы будем говорить, что имеет место Рфу) тогда и только тогда, когда найдется контур С в G такой, что имеет место Р(,(у, Q. Очевидно, что если имеет место P(;(v), то существует минимальное Fl’S F в G, со- держащее v, т к. найдется некоторый контур С, содержащий v, и по крайней мере одна вершина и в G, которая должна быть помещена в F, но с другой стороны, все контуры, которые разрушаются вершиной и, также разрушаются вершиной v для всех и из С. Это приводит к следующей реализации оператора 2—3 процедуры SIMPLIFY: 2. пока Существует некоторая вершина v такая, что имеет место Pg{v) 3. цикл F <- F'u {v}; G <- G - {v} все; Трудоемкость процедуры SIMPLIFY равна О(|/П х п (п + т).
Гпава 4. Сводимые и регуляризуемые графы 37 У Мы используем процедуру SIMPLIFY для определения класса /vs-простых орграфов. А именно, назовем орграф G fvs-простым, если процедура SIMPLIFY, имея на входе граф G, дает на выходе минимальное множество FVS F для G. Легко увидеть, что для /vs-простых орграфов имеет место равенство F(G) = c(G), где c(G) есть число вер- шинно-различных контуров в G. А. Классы сводимых и циклически сводимых графов суть подклассы класса /vs- простых графов. 4.4. Перечисление путей Многие задачи, встречающиеся в таких областях, как оптимизация кода, проверка правильности программ, тестирование программ и диагностика ошибок, требуют анализа потока данных по управляющему графу программы. В качестве составной части решения этой задачи возникает задача перечисления простых путей. Для ее решения в данной главе предлагаются два подхода. Первый основан на создании та- кой последовательности вершин, что любой простой путь есть подпоследователь- ность ее, а второй основан на собственно перечислении путей, что дает возможность избежать повторного прохождения уже пройденных сегментов любого простого пу- ти. Предлагаемые алгоритмы работают только со сводимыми графами, используя, например, тот факт, что в сводимом графе контуры могут быть упорядочены. 4.4.1. Сильные и слабые укладки Сильной укладкой графа называется такая последовательность вершин графа (воз- можно с повторениями), что любой простой путь в графе есть ее подпоследователь- ность. Слабой укладкой графа называется такая последовательность его вершин, которая содержит в качестве подпоследовательности любой несокращаемый путь в графе, т.е. такой путь ц = (vb ..., vt), что никакая его собственная подпоследовательность не является путем из V| в vk. Очевидно, что каждая сильная укладка одновременно является слабой. Имеют место следующие свойства. А. Каждый сводимый граф с п вершинами имеет сильную укладку длины не более чем п + сп log п, где с = 3 /(log у) = 5,13. Б. Для бесконечно многих значений п существуют сводимые графы с п вершинами и полустепенями захода и исхода, не превосходящими двух, для которых слабая уклад- ка имеет длину по крайней мере (1 /2) log п — О(п log и). Назовем областью R с головной вершиной h сводимого уграфа G = (К, Е) такой его фрагмент (И", £), для которого справедливы следующие свойства: □ если (v, vv) е Е и w g V', причем w * h, то v е К"; □ если (v, w) е Е, v е К'и w Ф И, то (v, w) е Е'.
312 Часть I. Обработка и визуализация графов Нетрудно видеть, что R является альтом, поскольку единственный способ попасть в область R— это пройти через его головную вершину И. Заметим также, что Е' со- держит все дуги из И'хИ'за исключением тех, которые заходят в головную вершину, беря начало внутри области. Известно, что существует такое упорядочение вершин сводимого уграфа, что любой путь, не использующий обратных дуг, есть подпоследовательность упорядоченной последовательности вершин. Назовем такое упорядочение ациклическим. Можно по- казать, что если путь входит в область R через головную вершину, то он должен сле- довать по подпоследовательности ациклического упорядочения, пока не покинет эту область. Введем теперь специальный класс сводимых графов, так называемые спиральные графы, для которых легко строятся требуемые последовательности вершин. Так как любой сводимый граф достаточно просто преобразуется в спиральный, то последова- тельность вершин для спирального графа также просто преобразуется в последова- тельность вершин для исходного. Класс спиральных графов определяется рекурсивно с помощью следующих трех правил. 1. Отдельная вершина есть спиральный граф. 2. Если G = (И, Е, s) есть спиральный уграф, v— новая (не принадлежащая G) вер- шина, а Е'— это множество дуг из каждой вершины м е И в вершину v, то спи- ральными являются уграфы: а) (Ио {v}, Елл E'^j {(v, s)}, s), 6) (Ko {v},EuE'u {(v, $)},*)• 3. Граф, отличный от определенных выше, не является спиральным. На рис. 4.32 изображены два способа конструкции спиральных графов, описанных в правиле 2 определения. Рис. 4 32. Конструкции спиральных графов При построении спирального графа вершины добавляются к нему в определенном порядке. При этом дуги, исключая дуги (v, s), добавляемые по правилу 2, как бы "ввинчиваются" в него, т. е. вначале к графу присоединяются их концы, а затем нача- ло, поэтому начала дуг располагаются дальше от "центра" графа.
Глава 4. Сводимые и регуляризуемые графы 313 Вершину v, добавляемую к спиральному графу по правилу 2, а, называют ведомой вершиной, а добавляемую по правилу 2,6— ведущей вершиной. Начальная вершина спирального уграфа — всегда ведущая вершина. В. Каждый спиральный граф сводим, и все спиральные графы, из которых он обра- зован, представляют собой его области. При этом дуги, добавляемые по правилу 2, а, исключая дугу (у, s), и дуга (v, s), добавляемая по правилу 2, б, являются дугами вперед, остальные добавляемые дуги— дугами назад, а каждая ведущая вершина доминирует над ранее добавленными. В основе алгоритма построения требуемой последовательности вершин лежит сле- дующее свойство. Г.Пусть G— спиральный граф, образованный вершинами vb ..., Vt, добавлявшимися именно в таком порядке. Пусть G'— спиральный граф, состоящий из вершин v2,..., v; । и дуг между ними в G. Пусть G"— спиральный граф, образованный вершинами v„ v, ь ..., и всеми дугами между ними. Пусть А и В — укладки графов G'u G", и пусть А и В — множества вершин соответственно G'u G", взятых в ациклическом порядке. Тогда АВВАВ —укладкауграфа G. Можно расширить данное свойство так, чтобы было возможным применять его для разбиения спирального графа на три части, одна из которых состоит из одной верши- ны. Д. Пусть уграф G определен, как выше, подграф G'порожден вершинами vb ..., vz i, а подграф G"порожден вершинами у,.,, ..., v2, Пусть А и В — укладки для G'u G" соответственно, и пусть А и В — ациклические упорядочения этих графов. Тогда ABBAv, ВВАВ —укладкауграфа G. 4.4.2. Построение укладок В основе построения укладки длины О(п log ri) для любого сводимого уграфа с и вершинами лежит разбиение графа на куски, причем никакой из них не превосхо- дит двух третей целого графа. Куски сами по себе— это области R, и последователь- ности вершин для них находятся рекурсивно. Потом мы образуем подграф спираль- ного графа стягиванием каждой из этих областей R в отдельную вершину vJ{. Требуе- мая последовательность вершин находится, если взять последовательность вершин для спирального графа и подставить ациклически упорядоченные последователь- ности вершин области R на место вершины vK. Пусть G = (И, Е, s)— уграф с k > 1 вершинами. Тогда мы можем найти множество непересекающихся областей R\,..., R„„ объединение которых включает все вершины графа G, причем: □ ни одна из областей Rb ..., R„, не имеет более чем (2/3)к вершин; □ существует последовательность областей Sb ..., S„, такая, что: •
314 Часть I. Обработка и визуализация графов • для I > 1 область S, состоит из областей S,_| и R„ причем одна предшествует другой; • S,„ есть G; граф, образованный из G стягиванием каждой из областей Rt,R,„ в отдель- ную вершину без петель, есть спиральный граф, в котором, быть может, не удалена ни одна дуга. Рассмотрим следующую ВУ-программу. начало 1. Г <-G; 2. пока Т имеет больше, чем (2/3)к вершин цикл 3. Пусть Т составлена из областей G и Т2, причем Ti имеет не меньше вершин, чем Т2; 4. печать (П, Т2); 5. Тч-Тт все печать (Г, 7); конец Этот алгоритм будет порождать последовательность пар (S„„ R,„), Rni-i), (Si, Ri). Пусть G— сводимый граф, разбитый на области Rh R„„ как это указано выше. Пусть для ! е [1 : m] R, имеет укладку А, и циклическое упорядочение А,. Построим спиральный граф Н стягиванием в G каждой области R в отдельную вершину и до- бавлением некоторых дуг (для получения спирального графа). Пусть В— укладка для Н. Построим последовательность С, заменяя в В каждое вхождение вершины v, из Н, изображающей /?,, на ациклическую упорядоченность Я,)]. Тогда А\А2 .. АтС есть укладка для G. 4.4.3. Постановка задачи перечисления Алгоритм перечисления путей для потокового анализа, описываемый ниже, обобща- ет метод укладок в том плане, что если прохождение вершин графа в соответствии с некоторой его укладкой гарантирует, что каждый простой путь будет пройден, то алгоритм перечисления путей дополнительно дает механизм для устранения повтор- ного прохождения уже пройденных сегментов любого простого пути. Алгоритм име- ет трудоемкость О(п а(п, и)), где a(n, п)-— очень медленно растущая функция, об- ратная функции Аккермана. Пусть G = (V,E,s) — сводимый граф и DT — его доминаторное дерево. Будем пред- полагать, что в G проведен поиск в глубину, вершины получили Л/-номера и дуги разбиты на древесные, прямые, поперечные и обратные. Можно показать, что для определения порядка обработки вершин из V существует индексирующая функция LNDEXfP), обладающая следующим свойством. Если р = (vb v2, v*)— произволь-
Глава 4. Сводимые и регуляризуемые графы 315 ный путь в K(G) (каркас— бесконтурный орграф, получающийся из G удалением обратных дуг) и вершины DT обрабатываются в порядке возрастания их номеров, специфицированных функцией INDEX, тогда вершины в пути р обрабатываются в порядке vA, v*_i,..., v,. Обратно, если вершины обрабатываются в порядке убывания их номеров, специфицированных функцией INDEX, тогда вершины в пути р обраба- тываются в порядке р\, р2,..., рк- Рис. 4.33 иллюстрирует это утверждение. В графе на рис. 4.33, а показаны Л/-номера вершин и дерево поиска в глубину. На рис. 4.33, б второе число в паре, нумерующей вершину, есть значение функции INDEX. Доминаторное дерево изображено пунк- тирными линиями, сплошными линиями изображены дуги из K(G). Пусть р = (1, 7, 2, 4,3). Тогда INDEX(3) < INDEX(4) < INDEX(2) < INDEX(7) < INDEX(l). С этого момента мы будем предполагать, что доминаторное дерево ориентировано так, что прохождение дерева в постфиксном порядке влечет прохождение вершин в возрастающем порядке специфицированных функцией INDEX номеров. Рис. 4.33. Порядок обработки вершин уграфа 4.4.4. Формальная постановка задачи Пусть D есть проблемная область, удовлетворяющая аксиомам замкнутого полуколь- ца за исключением аксиомы правой дистрибутивности. Она заменяется аксиомой монотонности. Для большинства оптимизационных задач D есть совокупность ко- нечных множеств, причем роль сложения играет объединение множеств, а умноже- ния — пересечение множеств. Для такой области D из аксиомы монотонности следу- ет, что если х с у, тохпгсупгдля х,у, z g D. Пусть е = (х, у) — дуга в G, тогда через О(е) будем обозначать ее начало, а через Т[е)—ее конец. Аналогично, если р— путь в G, то через О(р) будем обозначать его начало, а через 7’(р) — его конец.
316 Часть I. Обработка и визуализация графов Под прямой задачей анализа потока данных или кратко задачей прямого потока (FFP) будем понимать построение для данного сводимого графа G с заданными веса- ми дуг С(е) ("стоимостная" функция С : Е —> D) и с заданной начальной разметкой вершин /: V—> D отображения FF~. V —> D, удовлетворяющего следующим условиям: 1. Для каждого простого пути р справедливо включение FF(T(p)~) cz и u С(р) гт FF(Q(p)~), где С(р) — стоимость простого пути р, вычисленная исходя из стоимостей дуг. 2 Для любого отображения f. F D и для любой вершины v е V имеет место вклю- чение FF(y) 2 /(v), если для всех е е Е справедливо соотношение /(7(e)) с £/(Де))иС(е)п/(С>(е)). Заметим, что условие первое определяет поведение решения, в то время как второе условие утверждает, что решение должно быть максимальным. Из вида второго ус- ловия следует, что нужно рассматривать только простые пути, т. к. это условие для произвольного пути может быть выражено через соответствующие условия для про- стых путей. Предлагаемый здесь алгоритм анализа прямых потоков просматривает все контуры и для каждого контура определяет входной и выходной потоки. Пусть е е В— обратная дуга в G. Обозначим через CYCLE(e) множество вершин под е, т. е. CYCLE(e) = {х: х — вершина на пути Т(е)—DT >О(е)}. Ясно, что вершины из CYCLE(e) суть вершины контура, порождаемого дугой е. Определим множества ЕХ1Т(е) и ENTER(e). ENTER(e) = {х : х е T{f), где f есть путь(у15 у2, ..., yt-i, ук, х) такой, что П существует путь в K(G) изу2 в T{f) = х; Охе СГСЩе); О У\,у2, ...,ук £ CYCLE(e); О (У1,у2) е £}• См. рис. 4.34, а. ЕХЩе) = {х : х е O(f), гдеf есть путь (х,уь у2,...,ук_ъук) такой, что □ существует путь в Л'(О) из х в у*_ь П хе CYCLE(e)- о У1, У2, Ук г CYCLE(e); П (Ук 1,Ук) е В} См. рис. 4.34, б. Каждая вершина из ENTER(e) может рассматриваться как вершина, проводящая дан- ные между контурами CYCLEfe) и CYCLE(yt, у2\, аналогично, каждая вершина из
Гпава 4. Сводимые и регуляризуемые графы 317 ЕХ1Т(е) может рассматриваться как вершина, проводящая данные между контурами CYCLEfe) и CYCLE(yk_b у$. в) Рис. 4.34. Представление простого пути Следующее свойство специфицирует способ записи каждого простого пути, когда он заходит в контур и выходит из него. Это частное представление удобно для решения задачи FFP. А. Любой простой путь р с обратными дугами может быть записан в виде после- довательности b\, t2, b2, tt 1, Ьк-1, 4, в которой □ bi есть обратная дуга в G, 1 < i < к - 1; □ /,есть путь в K(G), который может быть представлен в виде DT „ К (С) 1)Г ч м<, = Г(о,)--> х,--——> у,---------> O(bi+\)=z„ где х, е EXlT(b]), у> е ENTERS,), 1 < i < к - 1; П f|, пути в K(G). Заметим, что все пути, упомянутые выше в свойстве 4.4.4, А, могут иметь длину 0. Свойство 4.4.4, А иллюстрируется рис. 4 34, в.
318 Часть I. Обработка и визуализация графов Свойство 4.4.4, А показывает, что поток данных вдоль простого пути может мыс- литься как состоящий из двух базисных чередующихся шагов — шаг внутри контура и шаг между контурами (в K(G)). Следующее свойство позволяет рассматривать кон- туры в G в некотором порядке, обозначаемом FL, при котором порядок, в котором встречаются обратные дуги в произвольном пути р, будет таким же, в котором эти дуги встречаются в FL. Порядок FL дает возможность вести обработку "цикличе- ских" вершин пути р в том порядке, в котором они встречаются в р. Рис. 4.35. Представление простого пути с обратными дугами Б. Для любого сводимого графа G существует упорядочение FL = еь е2, ..., е/,1, £/>, Ь = |В| обратных дуг такое, что если существует путь О(ех), 7{ех) *(О) >v где ех е B,v е ЕХЩе^) и и е ENTEE(e,), то Де,) непосредственно доминирует над Т(ех) в DT и 1 <x<j <b. Свойство 4.4 4, Б позволяет представить любой простой путь с обратными дугами в виде Z|, bi, t2, tk-\, bt-i, tk так, что b\, b2,..., ЪкЛ есть подпоследовательность по-
Глава 4. Сводимые и регуляризуемые графы 319 следовательности FL. Важно отметить, что разбит следующим образом: поток данных вдоль пути р может быть П поток данных к вершине vb V| е ENTER^bf); □ поток данных вокруг CYCLE(bt); П поток данных из щ е ЕХП\Ьх) в v2 е ENTER(b2); П поток данных вокруг CYCLE(b2) и т. д. (см. рис. 4.35). 4.4.5. Алгоритмы перечисления путей Последовательность пар (xf, X,1X-V,1+1,х, )...(х(i+l, х, ) называется представ- лением пути р = (Х|, х2, ..., х*), если р может быть записан в виде (х„х2,..., х )(х,1+1, ..., х,2)...(х( |+|, ..., х(( = хк). Сегмент пути р, соответствующий паре (х„ ху), есть подпоследовательность х„ х,+), . ., х7 пути р, 1 < i <j < к. Путь р мо- жет быть полностью представлен в конечной последовательности пар FPL - S\, S2, ,S„„ если существует последовательность множествр(/)...р(2)р(1), I > 1, такая, что: П р(1) содержит представление 5(1(1)5,2 (1)...S,; (1) пути р, где S, (1) есть /7-й эле- мент из FPL и ij< iji । для i <j < к; П если Sx(g) есть пара, принадлежащая одной из последовательностей в p(q), и Sxkq) не принадлежит множеству дуг Е, тогда представление 5,i(9 + 1)S',2(<7 + 1)...S',j (с/ + 1) для сегмента Sx(q) пути р помещается в p(q + 1); здесь снова S', (q +1) есть /,-й элемент FPL и i < /7+1 < х для 1 <J <х. Полное представление пути р в виде р(1)р(1 -1)...р(1) обозначают CR(p). Перечисле- ние путей для FFP(G, С, Г), т. е прямой задачи потокового анализа для графа G, ве- совой функции С и начальной разметки вершин /, есть конечная последовательность пар, в которой каждый простой путь в G может быть полностью представлен. Это перечисление путей обозначается через FPL(G). Для графа, представленного на рис. 4.36, множество пар FPLtkee для дерева поиска в глубину имеет вид: FP£7№£= (1,2)(2,3)(2,12)(3.4)(4,5)(5,6)(6,7)(7,8)(8,9)(9,10)(10,11)(11,12) Тогда FPL(G) = FPL, [(Ю,7)(7,8)(8,9)(9,10)]2 [(6,4)(4,5)(5,6)]2 [(11,3)(3,4)(4,6)(6,7)(7,10)(10,11)]2 [(13,2)(2,12)(12,13)]2 [(9,1)(1,2)(2,3)(3,7)(7,9)]2 FPL,нее. Здесь[...I2 означает, что содержимое скобок перечисляется дважды.
320 Часть I. Обработка и визуализация графов Рис. 4.36. Перечисление путей уграфа Рассмотрим путь р = (12, 13, 2, 3, 4, 5, 6, 7, 8, 9, 1), который может быть полностью представлен следующим образом: р(1) = (12, 13)(13, 2)(2, 3)(3, 7)(7, 9)(9, 1), р(2) = (3,4)(4, 6X6, 7X7, 8X8, 9), /ХЗ) = (4,5X5,6), с/?(р) = р(3)А2)А1). С этого момента будем обращаться к произвольной паре из FPL(CT) как к сегменту. Описываемые далее алгоритмы используют FPL(G) для контроля потока данных в С. Сегменты из FPL(G) будут обрабатываться слева направо. Во время обработки сег- мента £ константы в начальной точке 5 будут модифицированы с помощью стоимо- стной функции сегмента 5 и втянуты в конечную точку S. Поэтому с FPL(G) связыва- ется обобщенная стоимостная последовательность. Будем называть стоимостной последовательностью для FPL(G) = St,S2, ..., S,„ последовательность C(FPL(G)) = CIS}~), C'(S2), ..., C{Sm),
Глава 4. Сводимые и регуляризуемые графы 321 где C'(S,) = QS,), если S, — дуга из Е, и C'(S,)= UC(p(5,)) по всем p{S,) где/)(£,)— произвольный простой путь из O(S,) в T(S,~), в противном случае. Ниже мы не будем делать различия между С'и С, хотя и будем подразумевать под С обобщен- ную стоимостную функцию. Алгоритм, вычисляющий функцию FF для задачи FFP(G, С, Г), обрабатывает после- довательно слева направо сегменты из FPL(G). После завершения обработки всех сегментов можно утверждать, что: □ константы, сопоставленные начальной вершине сегмента 5, модифицированы стоимостной функцией С(5) и втянуты в конечную вершину 5; П стоимость C(S) сегмента S доступна как промежуточное значение для обработки последующих сегментов. Важность этих утверждений может быть проиллюстрирована на примере графа на рис. 4.36. Для него стоимость С(3,7) определяется с использованием промежуточных значений С(3,4), С(4,6) и С(6,7). (3,4), (4,6) и (6,7) суть сегменты в р(2), стоимость С(4,6) в свою очередь определяется с использованием значений С(4,5) и С(5,6). Если сегмент (4,6) появляется в представлении нескольких путей, предлагаемый алгоритм эффективен вследствие того, что С(4,6) доступна как промежуточное значение и не нужно перевычислять С(4,6) с помощью С(4,5) и С(5,6). Полезно также отметить, что алгоритм протягивает константы из каждой вершины пути/) в Т(р) в несколько приемов, как показано на рис. 4.37. Рис. 4.37. Этапы втягивания констант Ниже дается схема алгоритма протягивания констант на основе FPL(G) для фиксиро- ванного сводимого графа G. Алгоритм 4.11. Прямой потоковый анализ Дано. Управляющий граф G, заданный массивом из п = |G| вершин, с начальной разметкой I.
322 Часть I. Обработка и визуализация графов Требуется. Значения FF(I) Метод. начало 1. Построить доминаторное дерево DT для G; 2. Определить используя ОТ, перечисление путей FPL(G); 3. Определить C(FPL(G)Y, 4. Втянуть константы через FPL(G), используя C(FPL(G)) и возвращая FF, конец Алгоритм 4.12. Втягивание констант Дано. Последовательность пар PL = 5(1) 5(2)...5(|Р£|). Стоимостная последователь- ность C(PL). Требуется. FF'(i) для каждого i е V. Метод. начало 1. для каждого / е V цикл FF {/) = /(/') все 2 для / от 1 до |Р£| цикл 3. FF{T(S(/))) := FF\T(S(i))) гт [FF{O(S(/)) с C(S(i))) о FF{T(S(/)))] все; конец 4.4.6. Алгоритм прямого потокового анализа В этом разделе будет описан несколько модифицированный вариант алгоритма пря- мого потокового анализа из предыдущего раздела. Там перечисление путей на входе определялось до втягивания констант через выделенные пути. Алгоритм, предлагаемый ниже, втягивает константы через сегменты по мере того, как они добавляются к перечислению путей. Алгоритм втягивания констант, исполь- зуемый здесь, есть в точности алгоритм из предыдущего раздела. Алгоритм 4.13. Прямой потоковый анализ Дано. Управляющий граф G, заданный массивом из п = |G| вершин, с начальной разметкой 1. Требуется. Значения FF(T). Метод. начало 1. Построить доминаторное дерево DT для G; 2. возврат DT; 3. Определить, используя DT, перечисление путей и втянуть константы; 4. возврат FF; конец
Глава 4. Сводимые и регуляризуемые графы 323 Алгоритмы в этом разделе определяют перечисление путей, используя доминаторное дерево как основную структуру данных. Определим эту структуру данных и опера- ции над ней. Доминаторное дерево: DT: DT; массив из п вершин; nodefl): U(D, Другие атрибуты /]; другие атрибуты Г. [прямые дуги в вершину I, обратные дуги в вершину I, древесные дуги в вершину /, поперечные дуги в вершину /, стоимости дуг к непосредственным потомкам вершины / в G, стоимости дуг к непосредственным потомкам вершины / в DT, CEDTfl) = {е : Де) = / и О(е) и Де) не доминируют друг над другом в DT}, FF(T)]; Операции на DT: compress. Во время исполнения алгоритма compress видоизменяет DT для сохранения следов промежуточных значений (стоимостей), порождаемых для путей в DT. Алгоритм 4.14. Определение перечисления путей и втягивание констант Дано. DTкак определено выше; DT'; DT. Требу етс я. FF, FPLfG). Метод. начало 1. Инициализировать FPL, 2. Втянуть константы через дерево, используя FPL, DT', 3. выдать FPL, FF', 4. Втянуть константы через контуры, используя FPL, DT, 5. выдать FPL, FF', 6. Втянуть константы через дерево, используя FPL, DT', 7. выдать FPL, FF, конец Алгоритм 4.15. Втягивание констант через дерево Дано. FPL, DT. Требуется. FPL, FF'.
324 Часть I. Обработка и визуализация графов Метод. начало 1. для каждой вершины / в DT цикл 2 для каждой необратной дуги (J /) е Е цикл 3 Присоединить (J, /) к FPL, 4. возврат FPL; 5. Втянуть константы через (J, /), используя C(J, /); все все конец Алгоритм 4.16. Втягивание констант через контур Дано. DT. Требуется. FPL, FF'. Метод. начало 1. для каждой вершины / в DT цикл 2. % DT обходится в обратном порядке поиска в глубину % 3. Инициализировать LIST, C(LIST); 4 для каждой дуги е е CEDT(I) цикл 5 compress путь е; возврат LIST, C(LIST); 6 Втянуть константы через LIST, используя C(LIST), 7. Присоединить LIST к FPL и C(LIST) к C(FPL); 8. Инициализировать LIST, C(LIST); все; 9 для каждой обратной дуги е с Т(е) = I цикл 10. compress контур е; возврат LIST, C(LIST); 11. Втянуть константы через LIST, используя C(LIST); 12. Соединить LIST к FPL и C(UST) к C(FPL); 13 Инициализировать LIST, C(LIST); все все; конец Алгоритм 4.17. Сжатие пути между контурами — compress path Дано. Путь е. Требуется. Списки LIST, C(LIST). Метод. начало 1. IMMEDIA TE_PREDECESSOR := /£>( Т(е)); 2. PATH_NODES := последовательность вершин Xi, Хг, .... х* пути /О(Т(е)—>О(е)
Глава 4. Сводимые и регуляризуемые графы 325 3. compress IMMEDIATE-PREDECESSOR, PATH_NODES; 4. выдать LIST, C{LIST); 5. Присоединить e к LIST, 6. C(/D(T(e)),Це)) = C(/D(T(e)), T(e)) u C(/D(T(e)), O(e)) n C(e); конец Алгоритм 4.18. Сжатие контура — compress cycle Дано. Путь е. Требуется. Списки LIST, C(L1ST). Метод. начало 1. IMMEDIATE—PREDECESSOR := Т(е); 2. CYCLE_NODES := последовательность вершин Xi, х2.х* пути Т(е)—DT >О(е); 3. compress IMMEDIATE-PREDECESSOR, CYCLE—NODES; 4. выдать LIST, C(LIST); 5. Присоединить LIST к LIST; 6. Присоединить C(LIST) к C(LIST); конец Алгоритм 4.19. Сжатие — compress Дано. IMMEDIATE-PREDECESSOR, NODES, DT. Требуется. Списки LIST, C(LIST). Метод. начало 1. для каждой вершины I из NODES цикл 2. Присоединить I как непосредственного потомка для IMMEDIA TE_PREDECESSOR; 3. C(IMMEDIATE_PREDECESSOR, I) := C(IMMEDIATE_PREDECESSOR, /-1) n С(/-1./); 4. Присоединить (/-1, /) к LIST; Присоединить С(/-1, /) к C(LIST); все конец Рассмотрим пример, который иллюстрирует результаты применения к DT операции сжатия. Пусть граф G имеет вид, показанный на рис. 4.38, доминаторное дерево для него показано пунктирными линиями на рис. 4.39. Список путей для G имеет вид: FP£7№jX9,12)(12,13)(13,10)[(14,8)(8, 9)(9,13)(13,14)]2 (3,8)(8,9)(9,10)(10,11)(11,3)(3,4)(4,5)(5,7)(3,7)(7,6) [(6,3)(3,6)]2 [(I],!)(!,2)(2,3)(3,11)]2 FPLtree.
326 Часть I. Обработка и визуализация графов Рис. 4.38. Уграф G Рис. 4.39. Доминаторное дерево уграфа G
Глава 4. Сводимые и регуляризуемые графы 327 Пусть р = (4,5,6,3,8,9,10,11,1)— путь в G. Его представление имеет вид CR(p) - =р(1)р(0), гдер(0) = {(4,5)(5,6)(6,3)(3,11)(11,1)}, р(1) = {(3,8)(8,9)(9,10)(10,11)} Втягивание констант сквозь дерево дает FPLnun- = (1,2)(2,3)(3,8)(9,12)( 12,13)( 13,14)(9,10)( 13,10) (10,11)(3,4)(4,5)(3,7)(5,7)(11,7)(3,6)(7,6)(5,6). Рис. 4.41. Сжатие контура
328 Часть I. Обработка и визуализация графов Рис. 4.43. Сжатие контура, состоящего из вершин 1,2, 3, 11 Сжатие пути (9 -> 13) преобразует дерево DT к виду, показанному на рис. 4.40, и до- бавляет к FPL сегменты (9,12)( 12,13)( 13,10). Сжатие контура (8,14) добавляет сег- менты [(14,8)(8,9)(9,13)(13,14)]2; при этом DT преобразуется к виду, показанному на рис. 4.41. Сжатие пути (3 -> 11) добавляет сегменты (3,8)(8,9)(9,10)(10,11)(11,7) и преобразует DT к виду, показанному на рис. 4.42. Сжатие пути (3—> 5) добавляет (3,4)(4,5)(5,7). Сжатие пути (3 7) добавляет (3,7)(7,6); DT при этом не меняется. Сжатие контура (3,6) добавляет [(6,3)(3,6)]2 и оставляет DT без изменения. Сжатие контура (1,11) добавляет сегменты [(11,1)(1,2)(2,3)(3,11)]2 и преобразует DT к виду, показанному на рис. 4.43. Трудоемкость алгоритма прямого потокового анализа в основном обусловлена опе- рациями сжатия, проводимыми на доминаторном дереве DT. Для графа, требующе- го самое большее m сжатий на DT с и вершинами, полное число шагов равно
Глава 4. Сводимые и регуляризуемые графы 329 O(ma(ni, л)), где а — очень медленно растущая функция, обратная функции Аккер- мана. Библиографический комментарий Концепция управляющего графа как модели программы, описывающей структуру ее управ- ляющих связей, впервые рассматривалась в работах [18—19]. Понятия интервала и сводимого уграфа восходят к работам Дж. Кока [16, 29] и Ф. Аллена [24]; связь сводимости, аранжируемое™ и одновходовости уграфов установлена В. Н. Касьяновым [7, 46]. Он же ввел понятие регуляризуемости (обобщенной сводимости) уграфа и установил сводимость регуляризуемых уграфов (см например. [8, 111). Разборность как альтернативное определение сводимого графа, принадлежит М. Хехту и Дж. Ульману [41]. Иерархия вложенных зон рассматривалась в работах [25, 33], глубина интервалыю-сводимого уграфа и ее связь с длиной последовательности сведения — в работе [42] Понятие зонно- интервального представления было введено в работе [7], аранжируемости— в [20], одновхо- довости — в [7], а каркаса уграфа и запрещенного подграфа — в [42], базисных нумераций — в [9, 12]. Алгоритм проверки графа па сводимость разработан Р. Тарьяном (см., например, [64]); Да Хопкрофт и Дж Ульман дали его улучшенный вариант в [43] Отношения доминируемости (обязательного предшествования) впервые рассматривались в работе [51]; работы [50, 63, 6] содержат эффективные алгоритмы выявления отношения обяза- тельного предшествования. В работе [61] рассматривается задача инкрементального вычисле- ния доминаторных деревьев. В ней приводятся алгоритмы, инкрементально поддерживающие в корректном состоянии доминаторное дерево исходного уграфа произвольного вида в процес- се всевозможных вставок и удалений дуг уграфа. Возможность за счет расщепления вершин уграфа преобразовать любой уграф в эквивалент- ный ему сводимый граф впервые была доказана в работах Кока [30, 29, 16], который впервые описал "расщепление" вершины как такого эквивалентного преобразования, с помощью кото- рого всегда можно достичь сводимости любого уграфа. Разные стратегии выполнения указан- ных расщеплений в процессе трансляции программ с несводимыми уграфами рассматриваются вработах [7, 8, 13, 22, 26, 30, 34, 39, 44]. В работе [44] предложен подход, получивший название "контролируемого" расщепления вер- шин, и приведены результаты определенных измерений, подтверждающих его сравнительную эффективность. В этих измерениях на ряде тестовых примеров сравниваются по количеству вершин в результирующем уграфе три стратегии выполнения расщеплений вершин оптималь- ное (по числу вершин) расщепление, расщепление по Хехту [39]), а также введенное авторами "контролируемое" расщепление вершин. Однако, как показано в работе [15], даже для случая равновесных вершин уграфа любые последовательности растеплений вершин не всегда по- зволяют исходный уграф привести к эквивалентному ему сводимому графу с наименьшим числом вершин. В общей постановке задача экономного эквивалентного преобразования перегуляризуе- мых уграфов путем дублирования некоторых его вершин была сформулирована и решена В. Н. Касьяновым [15] Другие подходы к регуляризации неструктурированных программ рассматриваются в работах [27,48]. В отличие от подходов, ограничивающихся дублированиями вершин исходного угра- фа, они предполагают вставку в программу дополнительных переменных и операторов и. та- ким образом, увеличивают время счета по программе при ее регуляризации.
330 Часть I. Обработка и визуализация графов Различные направления в теории сводимых регуляризуемых уграфов изложены также в ра- ботах [2, 4, 6, II, 13, 23, 36, 40—42]. Разные характеристики, в том числе "неструктурности1 реальных программ исследовал Д. Кнут [47]. и Известно, что задача отыскания FAS— минимального множества дуг, удаление которых раз рушает все контуры в орграфе, есть WP-трудная задача [3, 45]. Также WP-трудной является задача об отыскании Fl'S — минимального множества вершин, удаление которых разрушает все контуры. Последняя, однако, допускает решение с линейной трудоемкостью для класса сводимых графов [57]. Поскольку обе задачи близки друг к другу, естественно ожидать, что алгоритм для решения одной может быть легко адаптирован к решению другой. Однако ре дукция задачи FAS к задаче Fl'S не сохраняет свойство сводимости, и поэтому опа не может быть использована в сочетании с алгоритмом решения задачи Fl'S, предложенным в [57], для нахождения FAS за полиномиальное время. Среди других работ на эту тему укажем [37. 56 65]. Задачи Fl'S/FAS часто встречаются в различных областях информатики. В области операцион ных систем к Fl'S сводится задача ликвидации тупиков [56], она же встречается при доказа тельстве корректности программ. FAS встречается при конструировании СБИС. Описываемый в данной главе алгоритм решения FAS для сводимых графов с взвешенными дугами принадле 'жит В. Рамачандрану [53—54] и основан на многократном использовании алгоритма для оты скания наибольшего потока в графах, образованных из исходного сводимого графа. Об алго ритмах построения таких потоков см. [21, 17, 1]. Один из наиболее эффективных алгоритмов построения наибольшего потока описан в [38]. Анализ различных потоковых алгоритмов дан в диссертации [35]. Особенность алгоритма Рамачандрана состоит в том, что он легко адаптиру- ется для решения FVS за полиномиальное время. Что касается общей задачи FAS для произвольных орграфов, известной также как задача о максимальном бесконтурном подграфе, то впервые она была рассмотрена в [58] для специ- ального класса орграфов, называемых турнирами. Позднее многие авторы рассматривали эту задачу с различных точек зрения. Базу для строгого изучения и улучшения полученных к времени результатов создала работа [28], в которой был предложен приближенный алгоритм отыскания разрывающего множества дуг с мощностью r(G) < m/2 - С|Л«/А1/2, где ct — некото- рая константа, а А — степень графа. Трудоемкость алгоритма — О(пт). Как развитие этого результата, в [31] был предложен более быстрый алгоритм (с трудоемкостью О(т)), дающий решение с верхней оценкой r(G)<m/2- п/6. Этот алгоритм описан в разд. 4.4.4. Для графов с небольшим числом дуг он эффективнее алгоритма Бергера-Шора; для плотных графов алго- ритм Бергера-Шора дает в некотором смысле оптимальное решение. Алгоритм GR, однако, на момент опубликования был единственным линейным алгоритмом, отыскивающим разрываю- щее множество с числом дуг, строго меньшим т/2, для всех орграфов. Тривиальные линейные алгоритмы были известны и раньше, но ни один из них не гарантировал указанной оценки даже для турниров. Алгоритм Бергера-Шора описан в разд. 4.4.4. I Понятие участка повторяемости программы, его польза для выполнения оптимизации про- грамм в содержательной постановке рассматривались А. П. Ершовым [3]. В работе Аллена [25] понятие зоны как участка многократного выполнения было введено и систематически изучено для разработки методов оптимизации программ с циклами. Иерархии вложенных зон про- грамм рассматривались в работах [32—33]. Крал [49] описал подход к оценке частоты выпол- нения операторов и переходов в программе, основанный на рассмотрении программы в виде однородной марковской цепи. Этот подход требует решения матричных уравнений и приводит к достаточно надежной информации о программе только в том случае, когда выбор того или иного преемника оператора осуществляется с постоянными (и известными) вероятностями независимо от того, какая последовательность операторов предшествовала выполнению дан- ного. При этом, как показано В. Н. Касьяновым [10], указанный подход не дает надежную ии-
Глава 4. Сводимые и регуляризуемые графы 331 формацию для программ с циклами, если рассматривать, как это было предложено И В. Пот- тосиным [20], для любой вершины р в качестве вероятности перехода по любой дуге, исходя- щей из р, величину 1/|ИСХОД(р)|. Описываемые в дайной главе метод и алгоритмы анализа циклической структуры графа программы были впервые введены В. Н. Касьяновым в работе [10] и взяты из его книги [13]. Рассмотренный в разд. 4.3 класс циклически сводимых графов был введен в работе [65]; там же был предложен эффективный алгоритм отыскания FVS для такого класса уграфов. Описа- ние класса М'5-простых графов, к которым относятся как сводимые, так и циклически своди- мые графы, ведется на основе работы Шпекенмейера [59]. Укладки сводимых графов описаны в работах |23] и [52] Алгоритм перечисления путей изла- гается в соответствии со статьей [55]. Он обобщает метод перечисления вершин в том плане, что если перечисление вершин гарантирует, что каждый простой путь в графе будет пройден, то алгоритм перечисления путей дополнительно дает механизм для избежания повторного прохождения уже пройденных сегментов любого простого пути. Алгоритм использует тот факт что в сводимом графе контуры могут быть упорядочены. Список литературы 1. Адельсон-Вельский Г. М., Диниц Е. А., Карзанов А. В. Потоковые алгоритмы. — М.: Нау- ка, 1975. 2. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции.— М.: Мир, 1978, —Т 2. 3. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые задачи. — М.: Мир, 1982. 4. Евстигнеев В. А. Применение теории графов в программировании. — М.: Наука. 1985. 5. Ершов А. П. Универсальный программирующий процессор// Проблемы прикл. математи- ки и механики.— М., 1971. — С. 103—116. 6 Касьянов В. Н. Анализ структур npoi рамм // Кибернетика — 1980. — № 1 — С. 48—61. 7. Касьянов В. И. Анализ управляющих графов программ// Системное программирова- ние.— Новосибирск, 1973. — Ч. II —С 133—154. 8. Касьянов В. Н. Введение в теорию оптимизации программ: Оптимизирующие преобразо- вания программ и их обоснование.— Новосибирск: ВЦ СО АН СССР, 1985. 9. Касьянов В. Н. Выделение гамаков в ориентированном графе // Докл. АН СССР. — 1975,—Т. 221, №5,—С. 1020—1022. 10 Касьянов В. Н К оценке частоты выполнения операторов и переходов в программе // Про- граммирование — 1975. — Т. 5. — С 64—72. 11 Касьянов В. Н. Методы анализа программ. — Новосибирск- Изд-во Новосиб ун-та, 1982. 12, Касьянов В. Н. Об одном алгоритме выделения бикомпонент в ориентированном графе// Системное и теоретическое программирование. — Новосибирск, 1974. — С. 235—243. 13. Касьянов В. Н. Оптимизирующие преобразования программ. — М.: Москва, 1988. 14 Касьянов В. Н. Теоретико-графовые задачи анализа управляющих графов транслируемых программ// Исследования по прикладной теории графов — Новосибирск; Наука. Сиб. отд., 1986. — С. 9—25
332 Часть I. Обработка и визуализация графов 15. Касьянов В. Н. Экономное преобразование несводимых графов// Системное и теоретиче- ское программирование.— Новосибирск, 1973. — С. 143—172. 16. Кок Дж Глобальная экономия команд// Тр 2-й Всес. конф, по программированию. Докл. иностранных участников. — Новосибирск: ВЦ СО РАН, 1970. — С. 40—48. 17. Липский В. Комбинаторика для программистов. — М.: Мир, 1988. 18. Мартынюк В. В. Выделение цепей в схемах алгоритмов // ЖВМ и МФ. — 1961. — Т. 1. № Г—С. 151—162. 19. Мартынюк В. В. Об анализе графа переходов для операторной схемы// ЖВМ и МФ.— 1965 —Т. 5, №2, —С 298—310. 20. Поттосин И. В. О линеаризации программы и частичном ее упорядочении И Системное и теоретическое программирование. — Новосибирск, 1972. —С. 278—286. 21. Форд Л. Р., Фалкерсон Д. Р. Потоки на сетях. — М.: Мир, 1966. 22. Aho А, V., Sethi R., Ullman J. D. Compilers: Principles. Techniques and Tools. — Addison- Wesley. Reading, Mass, 1988. 23. Aho A. V., Ullman J. D. Node listings for reducible flow graphs// J. Comp. Syst. Sci.— 1976. — Vol. 13. — P. 286—299. 24. Allen F. E. Control flow analysis// SIGPLAN Notices.— Pergamon Press, 1970.— Vol. 5, N 7, —P. I—19. 25. Allen F E. Program optimization// Annual Rev. Automat. Program.— 1969 —- Vol. 5.— P. 239—307. 26. Ammarguellat Z. A control-flow normalization algorithm and its complexity // IEEE Trans, Softw. Eng. — 1992. — Vol. 18, N 3. — P. 237—255. 27. Ashcroft E., Manna Z. The translation of "goto” programs to "while" programs// Proc. IFIP Cong 71. — Amsterdam: North-Holland Publ. Co., 1971. — P. 250—255 28. Berger B., Shor P. W. Approximation algorithms for the maximum acyclic subgraph problem// Proc. First ACM-SIAM Symp. on Discrete Algorithms — 1990. — P. 236—243. 29. Cocke J, Global common subexpression elimination // SIGPLAN Notices. — 1970. — Vol. 5, N 7. — P. 20—24. 30. Cocke J., Miller R. E. Some analysis techniques for optimizing computer programs// Proc, of the 2nd Hawaii Conf, on System Siences — IEEE, New York. 1969. — P 143—146. 31. Eades P.. Lin X., Smyth W. F. A fast and effective heuristic for the feedback arc set problem // Inform. Process. Lett. — 1993. — Vol. 47. — P. 319—323. 32. Earnest С. P. Some topics in code optimization // J. ACM. — 1974. — Vol. 21, N 1. — P. 76— 102 33. Earnest С. P., Balke К G., Anderson J. Analysis of graphs by ordering of nodes // J. ACM.— 1972 —Vol. 19,N L — P 23—42. 34. Erosa A. M., Hendren L. J. Taming control flow: a structural approach to eliminating goto state- ments // Proc, of the 1994 Intern. Conf, on Computer Languages. — IEEE, New York, 1994.— P. 229—240. 35. Fernandez-Baca D. F. Improved bounds for network flow algorithms with applications. PhD dis- sertation — Univ, of Calif, Davis, 1986. 36. Fong A., Ullman J. D. Finding the depth of a flow graph// J. Comput. and System. Sci.— 1977. — Vol. 15, N 4. — P. 300—309.
Глава 4. Сводимые и регуляризуемые графы 333 37. Garey М. R., Tarjan R. Е. A linear time algorithm for finding all feedback vertices // Inform. Process. Lett. - 1978. — Vol 7. — P 274—276. 38. Goldberg A., Tarjan R. E. A new approach to the maximum flow problem // Proc. 18th Annu. ACM Symp. on Theory of Computing. — 1986. — P. 136—146. 39. Hecht M. S. Flow analysis of computer programs. New York: Elsevier, 1977 40. Hecht M. S. Topological sorting and flow graphs // Proc. 1F1P Congress 74. — Amsterdam, 1974, —P 494—499. 41. Hecht M. S., Ullman J. D. Characterizations of reducible flow graph // J. ACM. — 1974. — Vol. 21, N 3. — P. 367—375. 42. Hecht M.S, Ullman J. D. Flow graph reducibility// SIAM J Comput.— 1972 — Vol. I, N2. —P. 188—202. 43. Hopcroft J. E., Ullman J. D. An n logn algorithm for detecting reducible graphs // Proc. 6th An- nual Princeton Conf on Inf. Sciences and Systems. — Princeton, 1972. — P. 119 44. Janssen J., Corporaal H Making graphs reducible with controlled node splitting// ACM Trans, on Program. Languages and Systems.— 1997. — Vol. 19,N6. — P. 1031—1052. 45. Karp R. M. Reducibility among combinatorial problems // Complexity of Computer Computa- tions.— Plenum, 1972. — P 85—103. 46. Kasyanov V. N. Some properties of fully reducible graphs // Inform. Process. Lett. — 1973. Vol. 2, N 4. — P. 113—117. 47. Knuth D. E. An empirical study of Fortran programs// Software—Practice and Experience. — 1971—Vol. LN2. P. 105—133. 48. Kosaraju S. R. Analysis of structured programs// J. Computer and System Sci.-— 1974.— Vol. 9, N 2 P. 232—255 49. Kral J. One way of estimating frequencies of jumps in a program // Comm. ACM. — 1968. — Vol. 11, N 7.— P. 475—480 50. Lengauer T„ Tarjan R. E. A fast algorithm for finding dominators in a flow graphs // ACM Trans, on Programm. Languages and Systems. — 1979. — Vol. 1, N 3. — P. 121—141. 51. Lowry E„ Medlock С. M. Object code optimization// Comm. ACM.— 1969 - Vol. 12, N 1,— P. 13—22. 52. Markowsky G., Tarjan R. E. Lower bounds on the length of node sequences in directed graphs // Discrete Math. — 1976. — Vol. 16. — P. 329—337. 53. Ramachandran V. A minimax arc theorem for reducible flow graphs// SIAM J. Discrete. Math. — 1990 - Vol. 3, N 4 — P. 554—560. 54 Ramachandran V. Finding a minimum feedback arc set in reducible flow graphs // J. of Algo- rithms. — 1988. — Vol. 9. — P. 299—313. 55. Ramanathan J., Kennedy K. Pathlistings applied to data flow analysis// Acta Informatica.— 1981—Vol. 16, N 3, — P. 253—273. 56. Rosen В. K. Robust linear algorithms for cutsets// J Algorithms.— 1982.—- Vol. 3.— P 205—217. 57. Shamir A. A linear time algorithm for finding minimum cutsets in reducible graphs // SIAM J. Comput. — 1979. — Vol. 8 N 4. — P 645—655. 58. Slater P. Inconsistencies in a schedule of paired comparisons// Biometrica.— 1961.— Vol. 48, —P. 303—312.
334 Часть I. Обработка и визуализация графов 59. Speckenmeyer Е. On feedback vertex sets and nonseparating independent sets in cubic graphs // J. Graph Theory. — 1988. — Vol. 12. — P. 405^112. 60. Speckmeyer E. On feedback problems in digraphs // Leet. Notes Comput. Sci.— 1990. — Vol. 411, —P. 218—231. 61. Speedhar V. C., Gao G. R., Lee Y-F. Incremental computation of dominator trees // ACM Trans, on Programm. Languages and Systems. — 1997. — Vol. 19, N 2. — P. 239—252. 62. Tarjan R. E. Depth first search and linear graph algorithms// SIAM J. Comput.— 1972.— Vol. 1,N2. — P. 146—160. 63. Tarjan R. E. Finding dominators in directed graph// SIAM J. Comput.— 1974.— Vol. 3, N L — P. 62—89. 64. Tarjan R. E. Testing flow graph reducibility// J. Comput. System. Sci.— 1974.— Vol. 9, N 3. — P. 355—365. 65. Wang C., Lloyd E. L., Soffa M. L. Feedback vertex sets and cyclically reducible graphs // J. ACM. — 1985, —Vol. 32. —P. 296—313.
ГЛАВА 5 Визуализация Визуализация сложных концептуальных структур является ключевой компонентой во многих приложениях в науке и технике. Граф — это абстрактная структура, кото- рая используется для моделирования информации. Графы применяются для пред- ставления любой информации, которую можно промоделировать в виде объектов и связей между объектами. Поэтому многие системы визуализации информации нуж- даются в таком рисовании графов, при котором получаемые изображения графов просты для рассмотрения и понимания. Сегодня автоматическая генерация изображений графов имеет много применений. Среди них технология программирования (управляющие графы, диаграммы потока данных, графы вызова процедур, иерархии объектно-ориентированных классов и т. д.), информационные системы (организационные схемы), базы данных (диаграммы связей объектов), системы реального времени (сети Петри, диаграммы состояний и переходов), системы поддержки решений (PERT сети, деревья активности), искусст- венный интеллект (диаграммы представления знаний), логическое программирование (SLD-деревья). Другие применения можно найти в иных научных и инженерных дис- циплинах, таких, как, например, медицина (концептуальные решетки), биология (де- ревья эволюции), химия (молекулярные изображения), гражданское строительство (схемы планировок этажей) и т. д. 5.1. Задача и методы визуализации В зависимости от применения элементы графа должны изображаться различными способами. Например, вершины могут быть нарисованы, например, в виде точек, кругов, прямоугольников или других геометрических фигур, или представлены неяв- но— через имена, которыми вершины помечены. Аналогично имеется большое раз- нообразие рисования ребер: например, в виде отрезков прямых, ломаных линий или кривых. Информация, сопоставленная элементам графа, может визуализироваться с использованием текстовых меток, расположенных внутри или рядом с графовым объектом, различными цветами или другими визуальными элементами, такими как, например, толщина линий или размер прямоугольников. Граф может рисоваться на плоскости или в трехмерном пространстве. Он может изо- бражаться целиком, частично или иерархически, например, путем стягивания неко- торых его подграфов в вершины, которые могут раскрываться по требованию.
336 Часть I. Обработка и визуализация графов 5.1.1. Рисование графов на плоскости Изображение, или лучше сказать расположение, графа на плоскости — это отобра- жение вершин и ребер графа в множество точек плоскости. Понятно, что один и тот же граф можно нарисовать многими способами (рис. 5.1), одни способы будут лучше других в разных приложениях. Понятие качественного способа рисования графа формализуется с помощью таких понятий, как изобразительное соглашение, эстетич- ность и ограничение. Изобразительное соглашение— это одно из основных правил, которому должно удовлетворять изображение графа, чтобы быть допустимым. Например, при рисова- нии блок-схемного представления программ можно использовать соглашение о том, что все вершины должны изображаться прямоугольниками, а дуги — ломаными ли- ниями, состоящими из вертикальных и горизонтальных звеньев. При этом, конкрет- ный вид соглашения реального применения может быть достаточно сложен и вклю- чать много деталей, касающихся изображения. Приведем некоторые примеры широ- ко используемых изобразительных соглашений. Полилинейное изображение предполагает, что каждое ребро графа рисуется в виде ломаной линии (рис. 5.1, а). Прямолинейное изображение характеризуется тем, что каждое ребро представляется с помощью отрезка прямой (рис. 5.1, б). Ортогональное изображение предполагает, что каждое ребро графа изображается в виде ломаной линии, состоящей из чередующихся горизонтальных и вертикальных сегментов (рис. 5.1, в). Рис. 5.1. Разнообразные изображения одного графа: а — полилинейное, б — прямолинейное, в — ортогональное, г — сетчатое
Гпава 5. Визуализация 337 Сетчатое изображение предполагает, что все вершины, а также все точки пересече- ния и сгибы ребер имеют целочисленные координаты, т. е. находятся в узлах коорди- натной сетки, образованной прямыми, параллельными координатным осям и пересе- кающими их в точках с целочисленными координатами (рис. 5.1, г). Плоское изображение предполагает отсутствие точек пересечения у линий, изобра- жающих ребра (рис. 5.2, а). Восходящее (соответственно нисходящее) изображение имеет смысл по отношению к ациклическому орграфу (дэгу) и предполагает, что каждое ребро орграфа изобра- жается кривой, которая монотонно не убывает (соответственно не возрастает) в вер- тикальном направлении. В частности, изображение является строго восходящим (со- ответственно строго нисходящим), если каждая кривая, изображающая дугу, строго возрастает (соответственно убывает) в вертикальном направлении (рис. 5.2, б). Рис. 5.2. Разные полилинейные изображения одного графа: а — плоское, б — строго восходящее Прямолинейное и ортогональное изображения являются частными случаями полили- нейных изображений. Полилинейные изображения предоставляют большую гибкость при рисовании графа, поскольку могут аппроксимировать изображения, использую- щие кривые линии для представления ребер. Между тем ребра, у которых количество сгибов превышает число три, могут быть сложны для восприятия. Прямолинейные изображения являются общепринятым способом рисования графов в публикациях по теории графов. Ортогональные изображения широко используются в печатных схе- мах и в различных диаграммах, используемых разными технологиями программиро- вания. Планарные изображения весьма привлекательны, но не каждый граф имеет такое представление, т. е. является планарным. Ациклические графы, удобные для представления различных иерархических структур (например, PERT диаграмм), час- то изображаются как восходящие. Эстетические критерии специфицируют такие свойства изображений, которые же- лательно применять в такой наибольшей степени, как только это возможно, чтобы повысить наглядность изображения. Широко используются следующие эстетические критерии. Минимизация пересечений. Если изображение графа содержит много пересечений ребер, то трудно проследить взглядом, какие вершины связаны с какими. В идеале желательно иметь плоские (т. е. совсем без пересечений) изображения, но, к сожале- нию, не каждый граф является планарным. Нужно отметить, что необходимость ми-
338 Часть I. Обработка и визуализация графов нимизации пересечений возникает и как техническое требование, например, при про- ектировании интегральных схем. Минимизация сгибов. Этот критерий особенно важен для ортогонального размеще- ния, поскольку человеческий глаз может легко прослеживать связь по ребру, не имеющему сгибов вообще, либо по ребру с небольшим количеством сгибов, не опи- сывающем странные зигзаги на рисунке. Критерий является также важным с техни- ческой точки зрения, поскольку при конструировании СБИС сгибы являются потен- циальными местами неприятности. Минимизация области размещения. Способность построения небольшого размера изображений является существенной для многих применений, связанных с визуали- зацией графа, в которых экономия места на экране представляется весьма важным. Этот критерий применим только тогда, когда используемые соглашения не позволя- ют изображению произвольным образом уменьшать масштаб, например, при сетча- том изображении или при прямолинейном изображении, требующем, чтобы соседние вершины отстояли друг от друга не менее, чем на единичное расстояние. Площадь размещения может формально определяться различными способами. Например, можно ее определять через площадь минимального выпуклого многоугольника, по- крывающего рисунок (выпуклый каркас), или как площадь покрывающего рисунок наименьшего прямоугольника с горизонтальными и вертикальными сторонами. Максимизация разрешения. Этот критерий, требующий максимизации минимального угла между двумя ребрами, инцидентными одной и той же вершине, приобретает в настоящее время особую важность. Если граф изображается на экране монитора с низким разрешением, то необходимо, чтобы ребра расходились как можно шире. Этот критерий особенно важен при прямолинейных изображениях. Минимизация общей длины ребер. Критерий минимизации суммы длин ребер являет- ся осмысленным, только если используемые соглашения не позволяют произвольным образом уменьшать масштаб изображения графа. Минимизация длины ребра. Как и предыдущий, критерий минимизации максималь- ной длины ребра имеет смысл только тогда, когда нельзя произвольным образом уменьшать масштаб изображения графа. Унификация длин ребер. Этот критерий предполагает минимизацию максимального различия в длинах между линиями, изображающими ребра графа. Минимизация сгибов на ребре. Минимизируется максимальное число сгибов на од- ном ребре изображения графа. Унификация сгибов. Минимизируется максимальное различие по числу сгибов между парами различных ребер изображения графа. Максимальная симметричность. При изображении графа в наибольшей степени де- монстрируется существующая симметрия графа. Этот эстетически критерий поддает- ся большей формализации за счет введения математической модели симметрии гра- фов и их изображений. Минимизация коэффициента сторон Критерий минимизирует отношение длины большей стороны к длине меньшей стороны у наименьшего прямоугольника с гори-
Глава 5. Визуализация 339 зонтальными и вертикальными сторонами, который покрывает изображение графа. Рисунок с высоким коэффициентом сторон будет трудно разместить на экране мони- тора, даже если он занимает площадь скромного размера. Большинство из рассмотренных эстетических критериев, как задачи оптимизации, являются сложными для решения с вычислительной точки зрения (см. приложе- ние 2). Поэтому обычно при построении изображений используются различные эври- стики и стратегии приближенных решений. Ограничения Если соглашения и эвристики являются общими правилами и критериями, которые формулируются по отношению ко всему графу и его изображению, то ограничения относятся к отдельным подграфам и частям изображений. Наиболее часто рассмат- риваются следующие ограничения. Центр. Требуется разместить заданную вершину ближе к центру изображения. Внешность. Требуется разместить заданную вершину на внешней границе изобра- жения. Кластер. Требуется разместить заданное подмножество вершин рядом друг с другом. Последовательность слева направо (сверху вниз). Требуется нарисовать заданный путь горизонтально слева направо (соответственно сверху вниз). Методы рисования Большинство методологий рисования графа основывается на следующих простых наблюдениях: □ эстетические критерии часто противоречат друг другу и, таким образом, поиски компромиссов неизбежны; П даже если эстетические критерии не конфликтуют, часто алгоритмически трудно удовлетворить всем им одновременно. Имеется ряд методов, которые позволяют получить удовлетворительные решения задач визуализации графов; основными среди них являются следующие. Планаризация. Плоские расположения обычно более привлекательны, чем неплоские. Плоские расположения являются весьма важными в технологиях печатных плат с точки зрения минимизации размещения. К сожалению, на практике многие графы не являются планарными. Можно пытаться сделать граф планарным либо удаляя из него как можно меньше ребер (эта проблема является АТ’-полной), либо удалением тех ребер, чья вставка впоследствии может создать наименьшее число пересечений. Эта проблема минимизации пересечений является в общей постановке АТ’-трудной, но есть некоторые эвристики, которые позволяют получать вполне удовлетворительные результаты (см. разд. 5.2). Использование физических аналогий. Эти методы (см. разд. 5.1.3) интерпретируют граф при построении его изображения как физическую систему с силами между вер- шинами и пытаются минимизировать энергию системы для получения хорошего ри- сунка. Такого типа алгоритмы используются для рисования произвольных (разре-
340 Часть I. Обработка и визуализация графов женных) сетей, таких как блок-схемы, графы программного планирования, графы телефонных вызовов и т. п. Они также применяются для кластерных изображений. Сигаяма-подобные методы. Наиболее широко используемыми алгоритмами для по- уровневого рисования графов являются алгоритмы, относящиеся к классу, предло- женных Сигаямой. Они производят поуровневые (или иерархические) изображения, пытаясь также минимизировать количество пересечений или размер области разме- щения (см. разд. 5.3). Потоковые методы. Проблема минимизации числа сгибов может эффективно ре- шаться путем сведения ее к задаче потока в сети (см. разд. 5.1.2), по крайней мере в тех случаях, когда зафиксирована топология размещения. Те же самые методы мо- гут применяться для максимизации углов между ребрами. Графовые изображения, как правило, предназначены для визуализации информаци- онных моделей, обладающих семантикой и иерархической структурой. Поэтому важным аспектом рисования графов является расположение меток вершин и ребер изображаемого графа (см. разд. 5.1.5). Помеченные графы широко применяют- ся на практике: в транспортных схемах, диаграммах состояний, планах зданий и др. Другим важным аспектом проблемы рисования графов является адекватное пред- ставление иерархической структуры графа при его изображении (см. разд. 5.4). Рассмотренные методы используются для рисования статических графов. Однако есть ряд применений, требующих построения интерактивных изображений графов. Среди них: инструменты отладки, сохранение документов, модули отношений сущ- ностей, схемы СБИС, а также Web-графы (см. разд. 5.5). 5.1.2. Ортогональные изображения Методы исследования потока в сети можно использовать при решении разнообраз- ных проблем построения плоских изображений графа. В плоском полилинейном изо- бражении графа углы между ребрами и сгибы удовлетворяют геометрическим свой- ствами, которые естественным образом выражаются с помощью потоковой модели. Важным эстетическим требованием для плоских ортогональных изображений явля- ется минимизация количества сгибов. Пусть /’является ортогональным изображением планарного графа G. Тогда в Г можно выделить два типа углов: углы при вершинах, каждый из которых образован двумя ребрами, инцидентными одной и той же вершине, и углы при сги- бах, каждый из которых образован двумя соседними звеньями ребра. А. В плоском ортогональном изображении сумма размеров всех углов при одной вершине равна 2л. Б. Пусть f— грань плоского ортогонального изображения графа. Тогда сумма углов при сгибах и углов при вершинах внутри /равна п(р — 2), где р — количество углов, если f— внутренняя грань, и равна т.{р + 2), если f— внешняя грань. Пусть a(f) — общее число при вершинах внутри грани f Ясно, что, если G— бисвяз- ный граф, то a(j) — это число вершин (ребер) границы/
Глава 5. Визуализация 341 Для каждого ребра е = {р, q} графа G рассматриваются две возможные ориентации (р, q) и (q,p), которые называются стрелками. Пусть £>(р)— это количество стрелок, начинающихся вр, а £>(/)— это множество стрелок границы грани/ образующих ее обход в направлении против часовой стрелки. Значения а и р, ассоциированные со стрелками, определяются по следующим пра- вилам : П а(р, q) • л / 2 является углом при вершине р, образованным первым звеном стрел- ки (р, q) и следующей стрелкой обхода у р; □ Р(Л <?) “ эт0 количество сгибов вдоль стрелки (р, q) с углом л/2 на левой стороне. Ортогональное представление G описывает класс эквивлентных плоских изображе- ний подобной формы, т. е. с одними и теми же значениями аир, ассоциированными со стрелками G. Более точно, ортогональным представлением G является приписы- вание целых значений сс(р, q) и Р (р, q) всем стрелкам G так, чтобы выполнялись сле- дующие соотношения: П I < a (р, q) < 4; П ₽(р,9)> 0; □ £а(р,д) = 4; (р№>(р) □ еслиf— внутренняя грань, то ]Гсс(р, q) + р (q, р) - р (р, q) = 2а (f) - 4; □ если/— внешняя грань, то ^2«(р,д) + Р (<?, р) - Р (р, <у) = 2сс (/) + 4. (мМ/> На рис. 5.3 приведены примеры трех плоских расположений графа с одним и тем же ортогональным представлением. Каждая стрелка (р, q) изображения 5.3, а помечена парой (а(р, q), Р (р, q)~). Можно ассоциировать потоковую сеть S' с плоским изображением графа G следую- щим образом П узлами сети S являются вершины и грани G; □ узел р сети S, являющейся вершиной G, производит поток о (р) = 4; П узел сети S, являющийся гранью/графа G, потребляет поток ст (/) = 2а(/) - 4, если f внутренняя грань, и поток ст(/) = 2сс(/) + 4, если/ — внешняя грань; □ для каждой стрелки (р, q) графа G с гранями fug слева и справа соответственно, сеть S имеет две дуги (p,f) и (/ q), такие, что дуга (p,f) имеет нижнюю границу = 1, пропускную способность ц(р, f) = 4, стоимость = 0, дуга (f q) имеет нижнюю границу K(f g) = 0, пропускную способность ц(/, g) = + то, и стои- мость yff g) = 1.
342 Часть I. Обработка и визуализация графов Рис. 5.3. Три плоских изображения одного графа, имеющих одинаковое ортогональное представление Из определений следует, что S' удовлетворяет следующим свойствам: П поток по дуге (p,f), ассоциированной со стрелкой (р, q), представляет величину сс(р, q), т. е. размер угла, образованного в вершине р грани /; нижняя граница и пропускная способность показывают, что такой угол должен быть не меньше л/2 и не больше 2л; стоимость равна нулю, поскольку такой угол у вершины и не у изгиба; П поток в дуге (f, q), ассоциированный со стрелкой (р, q) представляет величину Р(/А q)-, т. е. число изгибов с углом л/2 в грани f вдоль ребра между гранями/ng; нижняя граница и пропускная способность показывает, что такое число должно быть неотрицательным и может быть неограниченным; стоимость равна единице, поскольку каждая единица потока в такой дуге соответствует изгибу. Общий объем потока, производимого узлами вершинами, равен общему объему по- тока, потребляемого вершинами гранями. Действительно, пусть п, m и г обозначают количества узлов, ребер и граней G, соответственно. По формуле Эйлера имеем n — m+r — 2 = 0. Следовательно, Е8(р)-Е8(/) = Е4-Е(2а(/)-4)-8 = = 4и — 4m + 4г — 8 = 4(п — m + г — 2) — 0. Пусть G — плоский граф с п вершинами. В. Потоковая сеть S, ассоциированная с S, имеет О(п) углов и дуг и может быть построена по G за время О(п).
Гпава 5. Визуализация 343 Г. Пусть S— потоковая сеть, ассоциированная с G, и (p,f) и (F, g) — дуги S, соот- ветствующие некоторой стрелке (р, q). Следующие соотношения однозначно связы- вают ортогональное представление G (данное значениями а « р) с потоком ф в се- ти S: Ф (р,Л = а(р, Я), q(f,g) = $(p, q)- Также стоимость потока ф равна количеству изгибов ассоциированного ортого- нального представления G. Указанные свойства позволяют сформулировать алгоритм 5.1. Алгоритм 5.1. Ортогональное представление Дано. Изображение плоского графа Gen вершинами, степени которых не превы- шают 4. Требуется. Ортогональное представление G с минимальным числом сгибов. Метод. проц ОРТОГОНАЛИЗАЦИЯ= 1. Конструируется потоковая сеть S, ассоциированная с G; 2. Вычисляется поток ф минимальной стоимости в сети S; 3. Вычисляется ортогональное представления G ассоциированное с ф все Д. Алгоритм 5.1 вычисляет ортогональное представление G с минимальным числом сгибов за время О(Т(п)), где Т(п) — время вычисления потока минимальной стоимо- сти в сети S, ассоциированной с G. Заметим, что простой алгоритм вычисления потока минимальной стоимости, бази- рующейся на стандартной технике увеличения потока вдоль пути минимальной стоимости, работает за время Т(п) = О(п2 log п) и использует О(п) памяти [11] Более сложный алгоритм, использующий разреженность сети S, занимает Т(п) = О(п1А log и) времени и О(п) памяти [140]. После того как ортогональное представление графа G построено, возникает задача компактификации -— конструирования по нему ортогонального сетчатого изображе- ния, которое является плоским и занимает область как можно меньшего размера. Пусть требуется построить такое ортогональное изображение Н, что граница каждой его грани имеет форму прямоугольника. Ясно, что в этом случае Н имеет не более 4 сгибов, которые могут находиться лишь в углах границы внешней грани. Алгоритм 5.2. Строго прямоугольная компактификация Дано. Такое ортогональное представление Н планарного графа Gen вершинами с максимальной степенью 4, что границы всех граней в Н имеют форму прямоугольников. Требуется. Плоское ортогональное сетчатое изображение Г графа G с ортого- нальным представлением Н и имеющее минимальные высоту, ширину, размер облас- ти размещения и суммарную длину ребер.
344 Часть I. Обработка и визуализация графов Рис. 5.4. Сети для ортогонального представления графа вместе с потоками максимальной стоимости: а — Seop, б — Seepm Метод. проц СТРОГО ПРЯМОУГОЛЬНАЯ КОМПАКТИФИКАЦИЯ = 1. Конструируются сети Saop и Seepm. ассоциированные с Н. Сеть имеет по одному углу для каходой внутренней грани Н плюс два специальных узла s и t, представляющих "нижнюю" и "верхнюю" области внешней грани (рис. 5.4, а). В Saop есть дуга (f, д) для каходой такой пары граней f и д, что нижняя граница у f является верхней границей у д, причем Щ д) = 1, p(f, д) = + со, y(f, д) = 1. Аналогично строится Seepm — см. рис. 5.4, б; 2. ВЫЧИСЛЯЮТСЯ ПОТОКИ МИНИМаЛЬНОЙ СТОИМОСТИ ДЛЯ Saop И Seepm (см. рис. 5.4, где числа, приписанные дугам, — это значения максимального потока); 3. Устанавливается длина каходого сегмента Н равной потоку В СООТВеТСТВуЮЩеЙ Дуге Saop ИЛИ Seepm все Рис. 5.5. Переход к ортогональному представлению с ортогональными гранями
Глава 5. Визуализация 345 Временная сложность О(л) шагов 1 и 3 алгоритма 5.1, а шаг 2 занимает О(пт log п) времени. В общем случае, когда грани не обязательно имеют форму прямоугольника, можно сначала преобразовать ортогональное представление в такое, в котором все грани прямоугольные, путем введения "невидимых" пустых ребер и фиктивных вершин рис. 5.5, а затем использовать алгоритм строго прямоугольной компактификации. 5.1.3. Использование физических аналогий При нахождении изображения графа можно рассматривать граф как систему тел с силами, взаимодействующими между телами, например, считая вершины графа те- лами, а ребра пружинами. В этом случае алгоритм находит конфигурацию тел с ло- кально минимальной энергией — так называемую конфигурацию равновесия сил, в которой каждое тело занимает такую позицию, что сумма всех сил, приложенных к телу, равна нулю. Алгоритмы рисования на основе физических аналогий довольно популярны, по- скольку физические аналоги, с одной стороны, делают алгоритмы рисования доста- точно прозрачными для понимания п простыми для реализации, а с другой, приводят к алгоритмам, дающим весьма хорошие расположения графов Наиболее простой подход состоит в использовании комбинации пружин и электрон- ных сил, когда каждое ребро рассматривается как пружина, а вершины считаются одинаково заряженными частицами, между которыми действуют силы отталкивания. Более точно, сила, приложенная к вершине р, определяется по формуле и=(р,ч)е/-: (р,ч)еИ2 где fu— сила растяжения, действующая на вершину р из-за пружины (p,q), а — эт° сила отталкивания, существующая между частицами р и q. По закону Фу- ке f„ пропорциональна разности между расстоянием от р до q и длиной пружины с минимальной энергией; а сила g^, следует обратному квадратичному закону. Пусть d(p'4) обозначает расстояние на плоскости между р и q. Тогда для х-й координа- ты силы F(p) можно использовать формулу U=(p,№ ‘KP’ri где k„\ kff^ — параметры, которые не зависят от позиции вершин на плоско- сти и интерпретируются следующим образом: □ /„— это естественная (с нулевой энергией) длина пружины между р и q. Если пружина имеет длину /„ (т. е. d(p, q) = 7„), то не возникает сил растяжения между pnq-
346 Часть I. Обработка и визуализация графов □ — коэффициент жесткости (упругости) пружины между р и q. Чем больше он, тем сильнее пружина стремится установить расстояние между р ид, равным □ — коэффициент силы отталкивания между р и д. Данная модель нацелена на удовлетворение двух эстетических требований: П силы пружины между соседними вершинами нацелены на то, чтобы расстояние между ними приблизительно равнялось П электронные силы должны гарантировать, чтобы вершины не приближались близко друг к другу. Эксперименты показали, что во многих случаях алгоритм рисования строит симмет- ричные изображения графа. Для получения более качественных изображений можно для пружин использовать не закон Фуко, а логарифмический закон, когда f =^«)100 ^(р-,д) Ju К ll 1VC5 . к xp~xq d(p,q) Однако эксперименты показали, что не всегда возрастание качества результирующих изображений в этом случае компенсирует увеличение вычислительной сложности. В конкретных приложениях за счет изменения значений параметров можно управлять наглядностью представления и выражением в рисунке семантики графа. Большое разнообразие алгоритмов можно использовать для нахождения такого рас- положения графа на плоскости, при котором достигается равновесие всех сил, дейст- вующих на вершины графа. Простейший из них — это алгоритм, который работает в два этапа. На первом этапе вершины размещаются на плоскости случайным образом. Второй этап — это последовательность итераций до стабилизации, на каждой из ко- торых вычисляются для всех вершин р силы F(p) и для тех из них, для которых F(p)*0, происходит перемещение вершины в направлении этой силы на расстоя- ние, пропорциональное модулю силы. Пропорция сдвига одна для всех вершин и яв- ляется еще одним параметром алгоритма. Алгоритм достаточно прост, но не всегда дает наиболее быстрый способ достижения равновесия. Вместе с тем он позволяет осуществить интуитивно понятный плавный переход от случайных размещений к конфигурациям равновесия сил. 5.1.4. Трехмерные представления Имеется громадное число методов представления графов на плоскости. Дополни- тельное третье измерение, однако, имеет ряд преимуществ. Оно позволяет более гиб- ко размещать элементы графа и вообще обходиться без пересечений. С другой сто-
Глава 5. Визуализация 347 роны, при использовании дополнительного измерения возникают новые проблемы, поскольку текущие устройства вывода являются двумерными по природе и поддер- живают ограниченные разрешение и область визуализации. Поэтому результирую- щие изображения усложняются и становятся трудными для просмотра. Эти недостат- ки можно преодолеть с помощью таких навигационных операций, как повороты, сдвиги и масштабирование. Указанные операции позволяют эффективно использо- вать область экрана и дают возможность пользователю разрешить неоднозначности для больших графов при сопровождении их общих абстрактных представлений. Воз- можность изменения точки зрения в 3D позволяет также снизить проблему пересече- ний ребер, связанную с двумерным изображением трехмерного графа на экране. Большинство широко используемых алгоритмов для рисования на плоскости отно- сится к следующим трем категориям: использование физических аналогий, поуров- невое расположение и ортогональное изображение графа. Первые два подхода есте- ственным образом переносятся на 3D, в то время, как ортогональные 3D изображения требуют разработки существенно новых алгоритмов. Расширение на 3D методов рисования, основанных на физических аналогиях, до- вольно очевидно и связано с включением в описание методов третьих координатах вершин. Однако прямое применение указанных методов и их вариаций имеет недос- татки, связанные с тем, что часто получаемая при их применении конфигурация рав- новесия сил является локальным, а не глобальным минимумом и не дает хорошего изображения графа. Другая проблема— это трудность включения в модель таких сил, которые позволяют бороться с высокой плотностью размещения ребер и их пе- ресечениями. Последовательность работы алгоритма поуровневого изображения графа на плоско- сти состоит из следующих 4 шагов (подробную информацию см в разд. 5 3) I. Сделать граф ациклическим. 2. Распределить вершины по уровням, т. е. разбить вершины графа на упорядочен- ную последовательность подмножеств таким образом, чтобы упорядочение под- множеств не противоречило ориентации дуг. Ввести пустые вершины, чтобы ис- ключить "длинные" дуги, т. е. проходящие через один или более уровней. 3. Переставить вершины на одном уровне так, чтобы уменьшить число пересечений. 4. Уменьшить число сгибов путем уточнения позиций вершин на каждом уровне. Многие из этих шагов алгоритма поуровневого изображения графов на плоскости можно применять напрямую к построению 3D изображений. При 3D изображении сначала нужно сделать граф ациклическим, а затем распреде- лить вершины по уровням. Барицентрическая эвристика применима для вычисления средних позиций для обеих координат точек плоскостей, формирующих уровни. Как и в случае 2D, коллизии могут возникать, если две или более вершины одного уровня имеют одно и то же множество соседних вершин. Разрешение этих коллизий путем разнесения вершин на предопределенное расстояние или за счет изменения позиций вершин в главном уровне является более сложной задачей в 3D постановке, посколь- ку не только размер, но и направление разнесения требуется определить таким обра- зом, чтобы не вносить новые коллизии в процессе ликвидации существующих.
348 Часть I. Обработка и визуализация графов Обычный подход состоит в том, чтобы за счет дополнительных ограничений умень- шить проблемы, вызванные наложением видимых ребер и вершин. Эти ограничения предполагают использовать для поуровневого размещения конус или цилиндр; в этом случае вершины одного уровня лежат на окружности. Другой стандартный подход для визуализации иерархических структур — это так называемое конусное дерево. В конусном дереве каждое поддерево ассоциировано с конусом, в вершину которого помещен корень поддерева, а по окружности основания размещены сыновья корня. Конусное дерево может быть ориентировано сверху вниз или слева направо. В последнем случае оно называется кулачковым деревом 3D ортогональные изображения графа размещают его вершины в узлы трехмерной решетки, имеющие целочисленные координаты. Ребра представляются последова- тельностью непрерывных сегментов линий решетки таким образом, чтобы не было пересечений и наложений. Поскольку каждый узел решетки лежит на пересечении трех линий, любой граф, допускающий такое 3D ортогональное представление, имеет вершины со степенями, не превышающими 6. Если разрешить представление вершин графа в виде кубиков, можно строить ортогональные изображения для произвольных графов Следующий алгоритм компактификации позволяет для исходного графа G = (K, £) с п вершинами степени не более 6 строить сетчатое ортогональное изображение, имеющее не более 7 сгибов на ребро, длину максимального ребра, не превышающую \б4п - 7, и область размещения, ограниченную параллелепипедом размера (з[л/77]+2) 5 [ч/^] (8[л^]-6) Алгоритм основывается на шаге предобработки для конструирования ориентирован- ного графа G', чья неориентированная версия содержит G. Затем алгоритм разбивает все дуги графа G' на три непересекающиеся подмножества, образующие остовные подграфы графа G и раскрашивает их в разные цвета. Каждый из трех остовных подграфов располагается в своей области, так что не мо- жет быть пересекающихся ребер с разными цветами. Чтобы получить изображение G алгоритм строит неориентированные ребра по дугам G'; те дуги G', которым нет со- ответствующих в G, просто не рисуются. Рис. 5.6. Изображение дуги графа линией с 7-ю сгибами
Глава 5. Визуализация 349 Все вершины графа G размещаются в квадраты 5 х 5 на плоскости Z= 0. Дуги одного подграфа рисуются на плоскости Z = 0, а двух других— соответственно над и под данной плоскостью. При этом каждая дуга на плоскости Z = 0 имеет не более 6 сги- бов, а вне— ровно 7 (рис. 5.6, отрезки 1,3, 5 и 7 имеют длину 1). 5.1.5. Изображение помеченных графов 1 визуализации графов часто возникает необходимость в изображении графа вме- с данными, являющимися метками вершин и ребер графа. Вместе с тем нет обще- мятых методов рисования помеченных графов, который бы рассматривал пробле- му рисования графа и расположения меток в комплексе. В существующих методах, сак правило, либо размещение меток осуществляется в основном вручную, либо, иучшем случае, используется алгоритм для размещения меток для уже построенно- го изображения графа. Среди требований, предъявляемых к изображению помеченных графов обычно вы- деляют три следующие: □ наглядность: метки имеют подходящий размер; □ недвусмысленность: каждая метка должна легко идентифицироваться ровно с одним элементом изображения графа; □ отсутствие наложений: метки не должны накладываться на другие метки или другие графические элементы изображения. Возможные места размещения меток у некоторого элемента называют потенциаль- ными позициями для метки данного элемента. Иногда с позицией связывается неко- торая стоимость, которая отражает качество размещения в ней метки в терминах свойств недвусмысленности и наложения с другими элементами и позволяет задать отношение предпочтения между позициями метки. Как помечаются элементы изображения, зависит от конкретной модели пометок. Наиболее часто используются следующие модели. Модель с фиксированными позициями Каждый графический элемент имеет конечное множество позиций для меток. Для меток точек обычно используются 2- и 4-по- зиционная модель (рис. 5.7, а). Модель с фиксированными позициями и масштабируемыми метками. Каждый гра- фический элемент имеет конечное множество потенциальных позиций для меток, в которых все метки могут изменять свой размер. Модель с перемещениями. Каждый графический элемент имеет некоторую фиксиро- ванную метку, которая может размещаться на любую позицию, касающуюся элемен- та. На рис. 5.7, б представлены модели с 1-, 2- и 4-перемещениями для точечных изо- бражений, в которых метки могут непрерывно сдвигаться в направлениях, указанных стрелками. На рис. 5.7, в изображена модель с перемещениями соседних точек, т. е. таких перемещений, при которых метка остается соседней к точке, но может произ- вольно вращаться.
350 Часть I. Обработка и визуализация графов 1-перемещение 6) Рис. 5.7. Модели для изображения помеченных графов а — 2- и 4-позиционная модель б — модели с 1-, 2- и 4-перемещениями, в— модель с перемещениями соседних точек По отношению к рассмотренным ограничениям возникает ряд общих проблем. Проблема разрешимости. Существует ли такое размещение меток, что каждый гео- метрический элемент получает метку, размещенную в одной из своих потенциальных позиций, и нет двух перекрывающихся меток? Задача разметки. В случае, когда проблема разрешимости имеет ответ да, найти та- кое размещение меток, что каждый геометрический элемент помечается меткой, раз- мещаемой в одной из его потенциальных позиций, и нет двух перекрывающихся меток. Проблема максимизации количества. Присвоить так много меток, как только это возможно, чтобы каждый графовый элемент был помечен не более одной меткой, размещаемой в одной из его потенциальных позиций, и не было двух перекрываю- щихся меток. Проблема максимизации размера. Найти максимальный масштабный коэффициент S и соответствующее присваивание меток так, чтобы каждый графовый элемент поме-
Глава 5. Визуализация 351 чался меткой, размещаемой в одной из его потенциальных позиций и масштабиро- ванной с коэффициентом 5, и не было перекрывающихся меток. Следует отметить, что проблема разметки является главной для изображения по- меченного графа: часто координаты в графе адаптируют до тех пор, пока не будет существовать изображение помеченного графа. Пусть Р— задача разметки и пусть А — алгоритм для Р. Тогда очевидно, что бинар- ный поиск по всем размерам меток, размещаемым алгоритмом А, решает проблему максимизации размера. Аналогично некоторый алгоритм, который решает проблему максимизации размера, также решает проблемы разметки и проблему разрешимости. Более того, оптимальный алгоритм для решения проблемы максимизации количества меток решает проблему разметки. Поскольку проблема изображения меток у точечных элементов и проблема их изо- бражения у линейных элементов являются частными случаями нахождения изобра- жений помеченных графов, ясно, что общая проблема по крайней мере также трудна, как проблема для точечных или линейных элементов. Многие из проблем, связанных с изображениями помеченных графов, являются WP-трудными. Это означает не только то, что нет известных эффективных (полино- миальной временной сложности) алгоритмов для решения этих проблем, но также то, что мало вероятно, чтобы они существовали. Если трудно ожидать оптимального решения, можно пытаться найти аппроксимирующие решения, "близкие" к опти- мальному. Для того чтобы оценить границы аппроксимации, используются следую- щие понятия □ 8—приближение. Полиномиальный алгоритм называется 5-приближенным алго- ритмом (£> 1) для минимизационной проблемы Р, если для каждого конкретного входа со значением оптимального решения ОРТ, он дает решение, которое не бо- лее, чем в 5 раз больше ОРТ. Аналогично для максимизационной проблемы 8-приближенный алгоритм дает решение, которое по крайней мере составляет 5 часть от оптимального. П Наилучший достижимый коэффициент производительности. Оптимизационная проблема Р имеет наилучший достижимый коэффициент производительности а, если существует а-приближенный алгоритм для Р и нет 8-приближенного алго- ритма для Р, лучшего, чем а (если не верно, что Р = NP). П СПП. Семейство {ЛЕ}Е приближенных алгоритмов для проблемы Р называется схемой полиномиальных приближений или СПП, если алгоритм /4Е является (1+Е)-приближенным алгоритмом и его время работы полиномиально от размера входа для фиксированного е. 5.2. Планарные графы и их изображения Когда требуется нарисовать граф так, чтобы сделать информацию, содержащуюся вето структуре, более наглядной, крайне желательно строить такие изображения, которые имеют как можно меньше пересечений ребер. Более того, часто возникают
352 Часть I. Обработка и визуализация графов ситуации, когда необходимо нарисовать граф на плоскости так, чтобы вообще не бы- ло пересечений. Например, в радиоэлектронике при изготовлении микросхем печат- ным способом электрические цепи наносятся на плоскую поверхность изоляционного материала и поэтому не должны пересекаться. Аналогичные ситуации возникают при проектировании железнодорожных и других путей, где весьма не желательны пере- езды. 5.2.1. Планарные графы и их свойства Плоским графом называется граф, вершины которого являются точками плоскости, а ребра— непрерывными плоскими линиями без самопересечений, соединяющими соответствующие вершины так, что никакие два ребра не имеют общих точек, кроме инцидентной им обоим вершины. Любой граф, изоморфный плоскому графу, называется планарным. Очевидны следующие утверждения: всякий подграф планарного графа планарен; граф планарен тогда и только тогда, когда каждая его связная компонента— планар- ный граф. О планарных графах говорят, что они укладываются на плоскости (имеют плоскую укладку). Можно рассматривать укладки не только на плоскости, но и на других по- верхностях и в пространстве. В них вершины изображаются точками, а для изобра- жения ребер используются жордановые кривые— непрерывные спрямляемые ли- нии, не имеющие пересечений. Изображенный таким образом граф G в пространстве L, что кривые, соответствующие различным ребрам, пересекаются только в инци- дентных этим ребрам вершинах, называется укладкой графа G в пространстве L. А. Каждый граф укладывается в трехмерное пространство. Б. Граф укладывается на сфере тогда и только тогда, когда он планарен. В. Почти все графы не являются планарными. Г. Связный граф планарен тогда и только тогда, когда каждый его блок (двусвязная компонента) планарен. Д. Всякий планарный граф с п> 4 вершинами имеет по крайней мере 4 вершины со степенями, не превосходящими 5. Операция подразбиения ребра и = {р, q} графа G состоит в замене его на два ребра {р, г} и {г, q}, где г— новая вершина. Два графа называются гомеоморфными, если оба они могут быть получены из одного и того же графа подразбиением его ребер. Теорема Понтрягина—Куратовского. Граф планарен тогда и только тогда, когда он не содержит подграфов, гомеоморфных К5 и К$ з, где К5 — полный 5-вершинный граф, а К3 3 — полный двудольный граф, каждая доля которого состоит из 3 вершин (рис. 5.8). Гранью плоского графа называется максимальное по включению множество точек, каждая пара которых может быть соединена жордановской кривой, не пересекающей ребра графа. Границей грани называется множество вершин и ребер графа, принад- лежащей этой грани. /
Глава 5. Визуализация 353 Рис. 5.8. Непланарные графы Ks и К3,3 Рис. 5.9. Плоская укладка с 4 гранями Всякий плоский граф имеет одну, и притом единственную, неограниченную грань (на рис. 5.9 грань 4); такая грань называется внешней, а остальные грани — внутренними. Нетрудно заметить, что всякую внутреннюю грань плоского графа G можно преобра- зовать во внешнюю с помощью подходящей стереографической проекции укладки G на сфере. Е. Плоский граф двусвязен тогда и только тогда, когда граница каждой его грани является простым циклом. Пусть и, m,f— соответственно число вершин, ребер и граней плоского графа Теорема Эйлера. Для всякого связного плоского графа верно равенство п — т + f= 2, называемое формулой Эйлера. Связный плоский граф называется плоской триангуляцией, если каждая его грань (втом числе и внешняя) является треугольником. Ж. Всякий плоский граф является остовным подграфом некоторой плоской триан- гуляции. Плоский граф называется выпуклым прямоугольным графом, если границей каждой его грани является выпуклый многоугольник. 1 Каждый планарный 3-связный граф имеет выпуклую прямоугольную укладку. Теорема Маклейна. Граф планарен тогда и только тогда, когда в каждом его не- тривиальном блоке есть такой базис циклов С|, С2, ..., С* и такой один дополни- тельный цикл Со, что любое ребро блока принадлежит ровно двум из этих k +1 циклов. Говорят, что два представления Dt и D2 планарного графа G на плоскости реализуют одну и ту же плоскую укладку G, если у них совпадают множества циклов графа G, являющихся границами граней, и внешняя грань в О, ограничена тем же циклом, что и внешняя грань в D2. Представление орграфа G = (И, £) называется восходящим, если для каждой дуги (p,q)eE ее представление монотонно не убывает по у-й координате при движении от р к q. Орграф G является восходящим тогда и только тогда, когда он допускает восходящее представление. Орграф G называется восходящим планарным, если он имеет восходящую плоскую укладку. 12 Зак. 202
354 Часть I. Обработка и визуализация графов Следующий алгоритм Хопкрофта — Тарьяна позволяет проверять планарность графа за линейное время. Можно считать, что G — двусвязный граф, поскольку по свойству Г всегда можно построить укладку G из укладок его блоков. Схема алгоритма для двусвязного G следующая. Вначале ищется цикл С, удаление которого нарушает связность графа G. Затем рекурсивно проверяется, являются ли планарные графы, конструируемые путем слияния связных компонент G\C и цикла С. На последнем шаге объединяются вычисленные укладки для компонент в одну укладку всего графа, если это возможно. В качестве основы алгоритм рассматривает дерево поиска в глубину G'= (И, Т, В) для графа G', где Т—древесные дуги, В— обратные дуги, а V— вершины, представлен- ные их Л/-номерами. Пусть С является позвоночным циклом для G, т. е. циклом, который состоит из неко- торого простого пути по G' от корня и одной обратной дуги, ведущей в корень. Если G — двусвязный граф, то С существует. Пусть удаление С разбивает G на связные подграфы Gh G2, ..., G*, и пусть G,' обозна- чает граф, состоящий из G„ цикла С и всех ребер между вершинами G, и вершина- ми С. Рекурсивно проверяется, являются ли все G,' планарными и строятся их плоские представления (в виде множеств циклов, являющихся границами граней) так, что все вершины и ребра С расположены на внешней грани. Чтобы проверить, можно ли объединить их в укладку G, строится граф переплетения 1(;. Вершинами этого графа являются подграфы G,, а дуги соединяют ребром вер- шины, соответствующие Gt и G,, если G, и G, переплетаются, т. е. их нельзя располо- жить в укладке G по одну сторону от С (рис. 5.10). G является плоским, если — двудольный граф. В случае двудольного графа 1С, укладка G может быть легко по- строена из укладок G,'. Рис. 5.10. Переплетающиеся графы б,и G,, которые нельзя разместить на одной стороне С
Глава 5, Визуализация 355 Другой линейный метод проверки планарности графа основывается на так называе- мой «/-нумерации. Нумерация g вершин графа G = (К, Е) называется st-нумерацией, где {«, /} е Е, если: g(«) = 1, g(t) = | и для любого ре И\{«,/} найдутся такие q,re V, что {р, г} е Ен g(q) < g(p) < g(r) Пусть G = (V, Е)— двусвязный граф и К= {pt, р2, ..., р„} — упорядоченные по воз- растанию номеров вершины графа в некоторой «/-нумерации G. Пусть G*— подграф графа G, порожденный множеством вершин {/?,,р2, ...,рк}. Этот граф расширяется до графа Вк следующим образом. Для каждого ребра {р, q} е Е такого, что р лежит в Gk и q не принадлежит Gk, граф Вк имеет новую виртуальную вершину и ребро, соединяющее р с этой вершиной. Таким образом, в Вк возможно существование целого ряда виртуальных вершин, соответствующих одной и той же вершине графа G. Идея алгоритма состоит в проверке, можно ли отождествить вир- туальные вершины, соответствующие одной и той же вершине G, без потери свойст- ва планарности. Если G является планарным, Вк имеет плоскую укладку, в которой каждая вершина р„ 1 < i < к, имеет у-координатой /, все виртуальные вершины размещены с у-координатой, равной к + 1, а все ребра— это различные монотонные по у кривые (это означает, что они могут пересекаться не более чем раз по любой горизонтальной линии). Такие представления называются кустами (рис. 5.11). Рис. 5.11. Куст, в котором все виртуальные вершины расположены су-координатой, равной 8
356 Часть I. Обработка и визуализация графов Пусть р,— некоторая вершина куста. Если удаление р, делает куст несвязным, то она называется точкой сочленения. Пусть В'— то, что получается после удаления Pi из куста В. Компоненты расщепления р,— это те компоненты у В', все индексы вершин которых превышают z. Рассмотрим куст (см. рис. 5.11). Поскольку метками вершин являются их ^/-номера, это куст графа Br Когда мы хотим нарисовать мы должны, во-первых, преобразовать куст так, чтобы все вершины, имеющие номер 8, образо- вывали бы слитную подпоследовательность на уровне 8. Это можно осуществить, например, обращая компоненты вершины 1 и вершины 4 (рис. 5.12). Уровень 8 7 б 5 4 3 2 1 Рис. 5.12. Преобразованный вид куста, в котором все вершины с меткой 8 расположены подряд Все возможные способы получения последовательного расположения вершин сле- дующего уровня могут быть представлены с использованием так называемого PQ-це- рева, позволяющего в случае планарного графа находить за линейное время соответ- ствующие перестановки для всех уровней графа. PQ-деревьями над множеством U называются деревья, чьи листья -— это элементы из V, а внутренние вершины распадаются на две группы; Р-вершины и ^-вершины. По- рядок расположения листьев дерева слева направо — это его крона. Рассматривается два типа преобразований на Р^-дереве: произвольная перестановка сыновей Р-вершины и обращение сыновей Q вершины. Кроны, получаемые выполнением ука- занных преобразований над Р£>-деревом, формируют множество перестановок листь- ев. Говорят, что Р(?-дерево описывает указанное множество перестановок своих листьев. Основанный на ^-нумерации алгоритм проверки планарного графа поддерживает в процессе своей работы некоторое Р(?-дерево. Когда добавляется новая вершина гра-
Глава 5. Визуализация 357 фа, над Pg-деревом выполняется так называемая редукция. После каждого выполне- ния редукции Pg-дерево в точности описывает множество возможных перестановок ребер, которые соединяются с G*, вдоль внешней грани плоского ^/-изображения Gk. Лвершины возникают из-за точек сочленения Gk, а g-вершины — из блоков Gk (рис. 5.13). Рис. 5.13. Граф Gk и его PQ-дерево 5.2.2. Рисование деревьев Простой и эффективный метод построения нисходящего плоского изображения кор- невого дерева Т состоит в использовании поуровневого расположения дерева, при котором вершины р глубины / имеют у-коордииату у(р) = а х-координаты при- сваиваются таким образом, чтобы разность x(j>”) - х(рг) имела тот же знак, что и раз- ность xipmeytp")) — xipmeijip')). Поскольку определение поуровневого однозначно фиксирует у-координаты всех вершин, тот или иной алгоритм, использующий эту схему, характеризуется правила- ми вычисления х-координат. Рис. 5.14. Поуровневое изображение бинарного дерева Простой метод присваивания х-координат вершинам бинарного дерева Т при его по- уровневом изображении состоит в определении х{р) как номера вершины при ин- фиксном обходе Т (рис. 5.14), однако такой метод имеет два недостатка: получаемый
358 Часть I. Обработка и визуализация графов рисунок бывает шире, чем необходимо; вершина-отец не обязательно центрируется по отношению к своим сыновьям. Указанные недостатки можно преодолеть с помощью следующего алгоритма Алгоритм 5.3. Поуровневое изображение дерева Дано. Бинарное дерево Т. Требуется. Поуровневое изображение дерева Т. Метод. функ ПОУРОВНЕВОЕ ИЗОБРАЖЕНИЕ(Т) = 1. если |7] = 1 то возврат Тривиальный рисунок 2. иначе L =Лев(Т); R := Прав(Т); 3. ПОУРОВНЕВОЕ ИЗОБРАЖЕНИЕ(Е); ПОУРОВНЕВОЕ ИЗОБРАЖЕНИЕ^); 4. если |L| * 0 и |R| * 1 то 5. Переместить изображение LwR друг к другу так, чтобы горизонтальное расстояние между ними стало равным 2 или 3, а расстояние между их корнями было четным 6. Разместить корень Т на одну единицу выше по вертикали и на одинаковом расстоянии от корней L и R 7. иначе Разместить корень Т и непустое поддерево L или Ктак, чтобы корень Т находился на единицу выше и на единицу правее от корня L или левее от корня R все все все Указанный алгоритм за линейное время О(п) строит изображение дерева в области размера О(и'), где п — число вершин в дереве. Данный алгоритм не всегда строит оптимальные по ширине изображения (рис. 5.I5). Вместе с тем, с помощью методов линейного программирования можно за полино- миальное время получать оптимальные по ширине изображения дерева, однако если требуется построить оптимальное сетчатое изображение, то эта задача является /VP-трудной. Алгоритм легко обобщается на случай, когда требуется изобразить произвольное корневое дерево. Некоторой вариацией поуровневого изображения дерева является его радиальное расположение, в котором уровни имеют вид концентрических окружностей, а подде- ревья занимают секторные сегменты (рис. 5.16). Выбор угла Рг секторного сегмента Wr для поддерева с корнем р определяется с уче- том числа вершин 1(р) в поддереве следующим образом. Пусть р лежит на уровне С„ тогда для каждого сына q вершины р имеем /(р) P7=min
Глава 5. Визуализация 359 Рис. 5.15. Примеры неоптимальной работы алгоритма поуровневого изображения дерева Рис. 5.16. Радиальное изображение графа
360 Часть I. Обработка и визуализация графов Рис. 5.17. Определение области размещения где т — это угол области Fp (рис. 5.17), определяемый точками пересечения а и b уровня Сц । и касательной к уровню С„ проведенной через точку р. Радиальное изображение часто используется для представления свободных деревьев, причем в качестве вершины, размещаемой в центре, берется одна из двух его цен- тральных вершин. Другой вид представлений деревьев — это так называемые Av-изображения. Av-изо- бражение бинарного дерева определяется как такое прямолинейное сетчатое распо- ложение, при котором для каждой вершины р выполняются следующие два свойства (рис. 5.18): П сын вершины р ставится в ряд за р либо по горизонтали вправо, либо по вертика- ли вниз; П не пересекаются минимальные прямоугольники с горизонтальными и вертикаль- ными сторонами, покрывающие разные поддеревья вершины р. Общая схема построения Av-изображения состоит в рекурсивном построении подде- ревьев с их объединением с помощью горизонтальной (или вертикальной) комбина- ции, когда левый (соответственно правый) сын размещается на единичном расстоя- нии от корня. Одним из часто используемых алгоритмов, уточняющих эту схему, является алго- ритм Av-расположения, при котором всегда реализуется горизонтальная комбинация, причем поддеревья одной вершины переставляются так, чтобы правое поддерево со- держало не меньше вершин, чем левое. Указанный алгоритм позволяет за линейное время О(п) размещать дерево в области шириной не больше п - 1 и высотой не больше log п, где п — число вершин. Этот алгоритм имеет хорошую оценку О(п log и) для размера области размещения, но не
Глава 5. Визуализация 361 очень хорош в смысле коэффициента сторон Q ------- . Для того чтобы улучшить log/? J этот коэффициент, нужно использовать как горизонтальную, так и вертикальную комбинации. Рис. 5.18. Пример йу-изображения бинарного дерева Рассмотренный алгоритм /iv-изображения бинарного дерева легко обобщается на случай произвольного корневого дерева с сохранением линейной временной сложно- сти и размера области размещения (рис. 5.19). наибольшее поддерево Рис. 5.19. Правила построения hv-изображения корневого дерева Так называемый метод Чана позволяет строить для бинарных деревьев плоское пря- молинейное строго восходящее и строго сохраняющее порядок изображение в облас- ти почти линейного размера. В простейшем виде он имеет вид, представленный алгоритмом 5.4, в котором левое и правое правила изображения имеют смысл (рис. 5.20). Алгоритм 5.4. Простое рисование Дано. Бинарное дерево Тс корнем р. Требуется. Прямолинейное плоское строго восходящее и строго сохраняющее порядок изображение Т.
362 Часть I. Обработка и визуализация графов Рис. 5.20. Правила размещения левого и правого поддеревьев Метод. функ ПРОСТОЕ РИСОВАНИЕ(Т) = 1. если |Т| < 1 то возврат Тривиальный рисунок 2. иначе L := flee(T); R := Прае(Т), 3. ПРОСТОЕ PHCOBAHHE(L); ПРОСТОЕ РИСОВАНИЕ(Я); 4. если |L| < |Я| то 5. возврат Комбинированное изображение L и R по левому правилу (см. рис. 5.20, б) 6 иначе возврат Комбинированное изображение L и R по правому правилу (см. рис. 5.20, е) все все все Очевидно, что высота полученного изображения Т равна п = | Т\. Оценка ширины не столь очевидна, однако для следующей переформулировки алгоритма может быть легко получена: функ ОБОБЩЕННОЕ РИСОВАНИЕ (Г) = 1. если|Т|<1то 2. возврат Тривиальный рисунок 3. иначе Рассматриваем некоторый путь Р = (ро = р, Pi, , р«) от корня р дерева Т к некоторому листу; 4. для i от 0 до к цикл 5. Пусть qi — брат вершины р, и D/— поддерево с корнем од 6. если Di * 0 то 7. ОБОБЩЕННОЕ РИСОВАНИЕ(а) все все 8. возврат Комбинированное изображение Р и всех Di по правому и левому правилу таким образом, что Р был вертикально расположен (рис. 5.21). все все
Глава 5. Визуализация 363 Рис. 5.21. Обобщенное рисование по Чану с использованием "жадной" стратегии выбора пути Алгоритм обобщенного рисования будет работать аналогично простому рисованию, если выбирать путь Р, используя "жадную" стратегию выбора и следующее правило: для любого / поддерево Т, с корнем /?, содержит не меньше вершин, чем поддерево D, с корнем qh являющего братом вершины /?,. К. Максимальная ширина W(ri) дерева с п вершинами равна О(и0'695). Дальнейшее уменьшение размера области размещения дерева можно осуществить следующим расширением левого и правого правил. Расширенное левое правило, примененное к корню р дерева Т, осуществляет переме- щение ограничивающего прямоугольника правого поддерева R на некоторое рас- стояние таким образом, чтобы х-координата корня R стала не меньше чем v-координата р. Расширенное правое правило определяется симметрично. Ясно, что оба правила по-прежнему гарантируют прямолинейную планарность и получение строго восходящего и строго сохраняющего упорядочение рисунка. Применение указанных правил позволяет строить прямолинейное плоское восходя- щее и строго сохраняющее упорядочение изображение высоты не более п - 1 и ши- рины О(4^1ов’2 ), а также строить для произвольного упорядоченного дерева прямо- линейное плоское строго восходящее и строго сохраняющее упорядочение изобра- жение в области размера О(п 4^1оЕг ). 5.2.3. Рисование последовательно-параллельных графов Последовательно-параллельные графы — это графы, конструируемые из базисного графа (рис. 5.22, а) с помощью последовательных композиций (рис. 5.22, б) и парал- лельных композиций (рис. 5.22, в). Поэтому с каждым последовательно-параллельным графом G естественным образом можно связать бинарное дерево Т, называемое часто декомпозиционным деревом (или
364 Часть I. Обработка и визуализация графов деревом разбора) графа G. Вершины Т принадлежат одному из трех типов: S-вершины, Р-вершины и (2-вершины. Дерево Т рекурсивно определяется по сле- дующим правилам. Если G— это единственное ребро, то Т состоит из единственной (2-вершины. Если G получается последовательной композицией из G' и G" (см. рис. 5.22, б) и Г и Т"— их декомпозиционные деревья с корнями р и q, то Т со- стоит из некоторой S-вершины, являющейся корнем Т и имеющей левым сыном р и правым сыном q. Аналогично, если G получается параллельной композицией из G'h G" (см. рис. 5.22, в), то Т состоит из некоторой Р-вершины, являющейся корнем и имеющей сыновьями р и q в произвольном порядке. Рис. 5.22. Рекурсивное определение последовательно-параллельных графов: а — базисный граф, б—последовательная композиция, в—параллельная композиция Каноническим декомпозиционным деревом Т для последовательно-параллельного графа G называется такое (не обязательно бинарное) дерево, которое получается из декомпозиционного дерева путем стягивания в вершины групп, соединенных между, собой S-вершин и групп, соединенных между собой Р-вершин. Каноническое дерево единственно для любого G с точностью до перестановки сыновей его Р-вершин и может быть построено за линейное время. Нетрудно убедиться, что для класса последовательно-параллельных графов G„, опре- деляемых способом, представленным рис. 5.23, любое восходящее прямолинейное сохраняющее расположение изображение требует области экспоненциального разме- ра, а именно £2(4"). Однако, если разрешать небольшие изменения в расположении, можно за линейное время строить изображение любого последовательно-параллельного графа в области размера £2(и2). В так называемом обзорном представлении графа каждая его вершина отображается в горизонтальный отрезок, а каждое ребро — в вертикальный. Построение такого изображения для последовательно-параллельного графа опирается на правила ком- бинирования рис. 5.24. В шинно-ортогональном изображении графа смежные его вершины соединяются посредством так называемых шин — некоторых горизонтальных отрезков, располо-
Глава 5. Визуализация 365 женных непосредственно под или над вершиной. Для последовательно-параллельных графов вершина источник имеет единственную шину, расположенную над ней, вер- шина сток имеет единственную шину, расположенную под ней, а любая другая вер- шина имеет ровно две шины: расположенные над и под вершиной (рис. 5.25). Оче- видны правила перехода от обзорного изображения последовательно-параллельного графа к его шинно-ортогональному изображению. G0 Рис. 5.23. Класс последовательно-параллельных графов Gn, требующих для своего расположения областей экспоненциального размера Рис. 5.24. Правила комбинирования изображений при построении обзорного представления графа
366 Часть I. Обработка и визуализация графов Рис. 5.25. Последовательность шагов по переходу обзорного изображения последовательно-параллельного графа к его шинно-ортогональному изображению 5.2.4. Рисование бесконтурных графов Будем предполагать, что исходный бесконтурный орграф G является так называемым st-графом, т. е. в нем имеется только одна начальная вершина, обозначаемая через s, и только одна конечная вершина, обозначаемая через t. Ясно, что любой дэг G может быть преобразован в лт-граф добавлением фиктивных вершин х и t, а также дуг (а, р) и (д, Г) для всех начальных вершин р и конечных вершин q графа G. Мозаичное представление планарного графа — это такое его изображение, в котором каждая вершина, ребро и грань изображается с помощью плитки — прямоугольника, стороны которого параллельны осям координат. Плитка может быть неограниченной или вырождаться и принимать вид отрезка или точки. Две плитки горизонтально (вертикально) инцидентны, если у них есть общая часть вертикальной (горизонталь- ной) стороны. Левая, правая, нижняя и верхняя координаты плитки 6 будут обозна- чаться через хД0), хн(0), у«(0) и у-/(0) соответственно. Пусть G— планарный .sT-граф, и пусть V, Е и F— множества вершин, ребер и граней графа G, где внешняя грань представлена в F двумя элементами х* и t, называемыми левой и правой внешней гранью G (рис. 5.26). Определим орграф G', ассоциированный с G, следующим образом (рис. 5.27, а): вер- шинами G* являются элементы из F и для любой дуги е 7 (i, /) в С граф G* имеет дугу е* = (f g), где f— левая по отношению к е грань, a g — правая, т. е. /= лев(е) и g = правде). Мозаичное представление 0 графа G — это такое отображение каждого объекта О из Vkj Е kj F в плитку 0(0), что справедливы следующие свойства (рис. 5.27, б): П если О\ * О2 то нет общих внутренних вершин у 0 (О,) и 0 (О2); П объединение всех плиток 0(0), О е Kkj Е kj F, является прямоугольником; □ 0(00 и горизонтально инцидентны тогда и только тогда, когда О( = лев(О2), или О| = прав (О2), или О2 = лев(О|), или О2 = npae(Oi)',
Гпава 5 Визуализация 367 s Рис. 5.26. Плоское изображение st-графа □ 6(0,) и 0 (О2) вертикально инцидентны тогда и только тогда, когда О, = кон(О2) или О, = моч(О2) или О2 =нач(О{) или О2 = ко//(О,). Алгоритм 5.5. Мозаичное представление Дано. Планарный st-граф G. Требуется. Мозаичное представление 0 для G, в котором каждая плитка— от- резок. Метод. проц МОЗАИКА = 1. Конструируется планарный st-граф G* Вершины ре V графа G помечаются числами У(р) таким образом, что Y(s) = 0 и У(р) > У(д) тогда и только тогда, когда (q, р) <= Е — дуга G 3. Вершины р' е V графа G* помечаются числами Х(р') таким образом, что X(s’) = 0 и Х(р*) > Х(д’) тогда и только тогда, когда (q*. р") е Е* — дуга графа G*. 4. Для всех элементов О g V ш Е uF вычисляются координаты 0(0) по правилам: х, (О) = Х(прав (О)), xR = X (лее(О)), ув(О) = У (прав(О)), уТ(О) = У (лее(О)) все Временная сложность алгоритма 5.5 составляет О(л), где п— число вершин исходно- го st-графа G Обзорным представлением Г заданного st-графа G называется такое его изображе- ние, в котором каждая вершина р представлена горизонтальным отрезком Г(р), назы- ваемым вершинным отрезком, а каждая дуга (р, q) — вертикальным отрезком Г(р, q),
368 Часть I. Обработка и визуализация графов называемым реберным отрезком, таким образом, свойства: что справедливы следующие три П вершинные отрезки не накладываются друг на друга; П реберные отрезки не накладываются друг на друга; П реберный отрезок Г(р, q) имеет нижнюю границу, лежащую на Др), и верхнюю границу, лежащую на Г(с/), и не пересекает ни один другой вершинный отрезок. 6) Рис. 5.27. Представления графа G: а — орграф G', б — мозаичное представление
Глава 5. Визуализация 369 Обзорное представление планарного 57-графа G может быть построено из мозаичного представления графа G с вырожденными плитками для вершин и невырожденными плитками для граней (рис. 5.28). Рис. 5.28. Пример конструирования: а — на основе его мозаичного представления, б— обзорного представления графа Легко конструируется полилинейное изображение планарного 57-графа G на основе его обзорного представления. Для этого каждая вершина G может быть представлена некоторой точкой соответствующего вершинного отрезка, а каждая луга (/?, с/) графа G ломаной не более чем из трех звеньев, среднее звено которой образовано частью реберного отрезка, изображающего эту дугу (р, q) (рис. 5.29). Алгоритм 5.6. Полилинейное изображение Дано. Планарный 57-граф G. Требуется. Восходящее полилинейное сетчатое изображение G. Метод. проц ПОЛИЛИНЕЙНОЕ ИЗОБРАЖЕНИЕ = Конструируется обзорное представление I графа G с целочисленными координатами вершин; 2. для каждой вершины v цикл 3. Заменить вершинный отрезок Г(и) на произвольную точку P(v) = (x(i/), y(i/)) отрезка Г (и) все, 4. для каждого ребра (л, и) цикл 5. если у (и) - у(л) = 1 то 6 % Короткое ребро % Заменить реберный отрезок Г(д, и) на отрезок с конечными вершинами Р(и) и Р(у) 7. иначе. % Длинное ребро % Заменить реберный отрезок Г(и, и) на ломаную линию соединяющую точку Р(п') с точкой Р(у) через точки (х(Г(щ и)), у(и) + 1) и (х(Г (и, и)), у(ц) - 1) все все все
370 Часть I. Обработка и визуализация графов Возможный выбор для размещения точки Р(у) — это середина вершинного отрезка Г(у). Пример полилинейного представления, полученного из обзорного представле- ния с помощью стратегии "размещения посередине", показан на рис. 5.29, а. О 1 2 3 4 5 6 7 б) Рис. 5.29. Полилинейные представления, полученные из обзорного представления графа с помощью: а — стратегий "размещения посередине", б — "выбора длинного ребра" Алгоритм 5.6 строит за время О(п), где и — число вершин исходного графа, плоское восходящее сетчатое изображение, в котором всего не более 6л — 12 сгибов, а каждое ребро имеет не более двух сгибов. Указанные характеристики получаемого изображения можно улучшить, если исполь- зовать специальное обзорное представление в качестве исходного и специальным
Гпава 5. Визуализация 371 образом выбирать позицию вершины Р(у). Можно осуществлять построение обзор- ного представления таким образом, чтобы оно содержало не менее и- 1 коротких ребер и имело размеры и х и. При выборе позиции вершины Р(у) в случае стратегии "выбора длинного ребра" можно всегда размещать ее на внешнюю границу вершин- ного отрезка (рис. 5.29, б). Так уточненный алгоритм будет за время О(и) строить полилинейное изображение графа в области размера О(и2) с общим числом сгибов (10 и-31)/3 и не более, чем с двумя сгибами на одном ребре. 5.2.5. Переход к планарному графу Рассматриваются следующие характеристики графов, представляющие ту или иную меру их непланарности. Род y(G) графа G — это наименьшее число ручек, которые нужно добавить к сфере, чтобы можно было граф G уложить на полученной таким образом поверхности Например, планарные графы G имеют род y(G)=0; графы К5 и К33 непланарны и у(К5) = у(К,.з)=1; Y(K,)=L(r-3)(r-4)/12j при r>3; y(Kr,,)=[(r-2)(s-2)/4j и у((7„) = 1 + (и - 4)2"-3, где Qn — «-мерный куб. А. Если G — связный т)-граф и п>3, то y(G)>((w— 3«)/6+lJ. k Б, Если Bh В2, , Вt— система всех блоков графа G, то у (G)=^y (/?,). i=i Числом скрещиваний cr(G) графа G называется наименьшее число пересечений, по- лучаемых при изображении графа на плоскости (понятие пересечения относится к пересечению ровно двух ребер). Например, Толщиной t(G) графа G называется наименьшее число его планарных подграфов, объ- единение которых дает граф G. Например, ,(&.) = [г +%J, t(Kr)= j7 +%j = If %(r + s-2))J’ Искаженностью sk(G) графа G называется наименьшее число ребер, удаление кото- рых приводит к планарному графу. Например, sk(Kr') = С? -Зг + 6, если и > 3. В случае, когда исходный граф G непланарен, можно преобразовать его в некоторый планарный граф G' с тем, чтобы затем применить один из алгоритмов плоской уклад- ки С и получить по ней изображение графа G.
372 Часть I. Обработка и визуализация графов Весьма радикальный способ сделать граф планарным — это удалить часть его вер- шин. Этот метод, однако, не используется при рисовании графов достаточно часто, поскольку удаление вершин значительно изменяет граф. Заметим, что проблема оп- ределения по целому числу к и графу G, можно ли сделать G планарным путем уда- ления к вершин, является NP-полной. Другой способ получения планарного графа G'— это расщепление вершин. Говорят, что граф С = (Р, Ег) получается из графа G = (Г, Е) расщеплением вершины р на qt и д2, если справедливы следующие два свойства: □ Г=(И{91,92})и{р}; □ Е = E\{{q, q,} : q е J" и {q, q,} e Г для / = 1 и i = 2}) u {{<?, p} :qe P{p} и {q, <?i} e £'или {q, q2} g £'}. Однако и этот способ построения G' также не является общепринятым и тоже связан с Л£-полной оптимизационной проблемой. Наиболее используемыми способами преобразования непланарного графа в планар- ный являются вставки новых вершин и удаления существующих ребер. Вставка вершин. Предположим, что исходный граф G непланарен и изображение D имеет к пересечений. Тогда мы можем преобразовать G в планарный граф G'. сделав каждую точку пересечения новой вершиной графа. Поскольку G' является планар- ным, можно к нему применить любой из известных алгоритмов рисования планарных графов, а затем перейти от полученного плоского изображения G" к изображению G заменив каждую ранее введенную вершину точкой пересечения ребер. Отметим, что проблема минимизации числа пересечений при изображении графа является WP-полной. Поэтому обычный эвристический подход состоит в использова- нии какого-либо алгоритма укладки непланарного графа с добавлением вершин вся- кий раз, когда возникают пересечения ребер. Другой широко используемый подход к получению планарного графа — это удале- ние ребер. В частности, каждое покрывающее дерево исходного графа G планарно, поскольку всякий ациклический граф является планарным. Вместе с тем проблема определения по графу G и числу к, существует ли планарная часть графа G с к ребрами, является WP-полной. WP-трудной является и проблема нахождения максимального по числу вершин планарного подграфа графа. Поэтому стандартный способ реализации нахождения планарного графа G' по G = (И, Е) путем удаления части его дуг связан с решением задачи максимальной (по включению) планарной части графа G. Эта задача может быть решена за полиноми- альное время и состоит в нахождении такого G'=( V’, Е1), где К'с И и £'с Е, что G'— планарный граф и любой граф G"= (£', Е"), где £'с £"с £, не является пла- нарным. Нахождение такого G' можно осуществлять по шагам, начиная с некоторого начального (им может быть граф (К, 0) или остовное дерево графа G) и добавляя на каждом шаге по одной дуге из G\G' без нарушения планарности до тех пор, пока не возникнет ситуации, когда нет дуги в G\G', добавление которой к G' не нарушает свойство планарности G'.
Гпава 5. Визуализация 373 Поскольку проверка планарности графа требует линейного времени, даже неизощ- ренная реализация рассмотренного способа требует О(п т), где и— число вершин графа G, а т — число ребер. Многие алгоритмы рисования работают лишь с 2- и 3-связными графами. Поэтому, если мы хотим применить такой алгоритм, следует увеличить связность исходного графа путем добавления новых ребер. После получения изображения увеличенного графа добавленные ребра можно удалить. Поскольку при таком преобразовании же- лательно не слишком увеличивать граф, можно пытаться минимизировать количест- во добавляемых ребер Однако проблема добавления минимального числа ребер к планарному графу так, чтобы результирующий граф был планарным и двусвязнЬм, является Л7’-трудной. Вместе с тем вполне удовлетворительного результата можно добиться с помощью приближенного алгоритма. Например, 5/3-приближенный алгоритм за время 0(ига(к, и)), где а— функция, обратная функции Аккермана, а к является О(п\ осуществляет преобразование планарного графа в планарный двусвязный граф. Алгоритм работает с Ьс-деревом исходного графа, в котором два типа вершин b-вершины и с-вершины, соответствующие блокам и точкам сочленения исходного графа (рис 5.30). Идея алгоритма состоит в добавлении ребер, сливающих пути по fcc-дереву в отдельные блоки до тех пор. пока все дерево не примет вид одной вер- шины и тем самым не станет граф 2-связным. Критическую роль при работе алгоритма играют концевые блоки (брелки)- 6-вер- шины бс-дерева степени 1. Алгоритм связывает ребрами концевые блоки между со- бой, если возможно, либо с неконцевыми блоками. Чтобы достичь коэффициента приближения, концевые блоки собираются в более крупные структуры, называемые
374 Часть I. Обработка и визуализация графов метками. Алгоритм просматривает эти метки в порядке убывания номеров концевых блоков и пытается соединить концевые вершины двух меток путем добавления но- вых ребер. Добавляемые ребра, которые соединяют концевые блоки двух меток, на- зываются сопоставляющими метками. Алгоритм выбирает определенные сопоставления, но поскольку результирующий граф должен остаться планарным, не все из них могут быть реализованы. Некоторые метки вообще нельзя сопоставить с другими и поэтому алгоритм также вводит ребра, которые соединяют концевые блоки одной и той же метки или ведут от одного из концевых блоков к неконцевой вершине вне метки. 5.2.6. Выпуклые представления Некоторые планарные графы можно нарисовать на плоскости таким образом, чтобы каждая граница грани являлась выпуклым многоугольником. Пример выпуклой пло- ской укладки приведен на рис. 5.31 Такое представление возможно для графа только тогда, когда границы всех граней являются простыми циклами. Таким образом, граф, не являющийся двусвязным, не имеет выпуклого представления. Рис. 5.31. Выпуклое представление графа Теорема Татта. Выпуклое представление существует у любого 3-связного графа Доказательство этой теоремы имеет вид алгоритма построения выпуклого представ- ления 3-связного графа, включающего решение О(п) линейных уравнений, где и — число вершин графа. Цикл грани— это такой цикл графа G, который является границей некоторой грани плоской его укладки. Выпуклым представлением S* цикла грани S является выпуклый многоугольник, в котором все вершины 5 изображены на границе S" и каждая верши- на 5* занята под вершину представления графа G. Представление 5* цикла S в виде многоугольника называется расширяемым, если существует плоское выпуклое пред- ставление графа G, в котором S’ является внешней гранью. А. Представление 5* цикла S графа G является расширяемым тогда и только тогда, когда выполняются следующие условия: • для каждой вершины р графа G, не лежащей на S, существует три непересе- кающихся по вершинам пути из вершины р к вершинам на 5;
Глава 5. Визуализация 375 • нет такой компоненты С в G\S, для которой все вершины на S, соседние не- которой вершина из С, расположены на одном и том же отрезке прямой Р многоугольника 5*; • не существует ребра, которое соединяет две вершины, лежащие на отрезке прямой многоугольника S*; • любой цикл в G, который не имеет общих ребер с S, имеет по крайней мере три вершины степени большей 2. Алгоритм 5.7. Выпуклое представление Дано. Граф G, границ в грани S графа G и расширяемое представление 5* грани £ в виде многоугольника Требуется. Выпуклое представление G. Метод. проц ВЫПУКЛОЕ ПРЕДСТАВЛЕНИЕ^, S, S’) = 1 Пусть G имеет более 3 вершин, и некоторые из них не принадлежат S; иначе выпуклое изображение уже построено; 2. Выбираем произвольную вершину р многоугольника S’ и рассматриваем G' = G \ {р}; 3. Разбиваем G'Ha блоки 61, .., В* сточками сочленения p-i, рг .... ры (см. рис. 5.32); 4. для всех Bi цикл 5. Строится изображение внешней границы S, блока В, таким образом, чтобы все вершины S;, которые не принадлежат границы S выпуклого многоугольника S’, помещаются внутри треугольника р, ph р^, причем в вершинах многоугольника S, размещались те вершины графа, которые смежны р, а остальные вершины границы S/ лежали на сторонах многоугольника S,’; 6. ВЫПУКЛОЕ ПРЕДСТАВЛЕНИЕ^,, S„ S’) все все Пара вершин {р, q} с Г графа G = (И, Е) называется разделяющей, если существует два подграфа G\ = (К(, £,) и С2 = (И2, £2), удовлетворяющих следующим двум свойст- вам: □ V=V^V2, Г|ПК2={р, q}\ □ Е=Е^Е2, Е|ПЕ2=0, |£,|>2, |Е2|>2. Разделяющая пара называется простой, если по крайней мере один из двух графов G, и Gz является либо 2-связным графом, либо имеет вид ребра, соединяющего две вер- шины степени большей, чем 2 Простая разделяющая пара называется запрещенной (FSP), если она имеет по край- ней мере четыре компоненты или такие три, ни одна из которых не является путем. Если граф G имеет FSP, то у него нет выпуклой укладки (рис. 5.33).
376 Часть I. Обработка и визуализация графов Рис. 5.32. Рекурсивное вычисление выпуклого изображения Рис. 5.33. Два примера запрещенной разделяющей пары {х, у} (раскрашенные области — подграфы) Рис. 5.34. Два примера критическом разделяющей пары {х, у} (заштрихованные области — подграфы) Простая разрезающая пара называется критической (CSP), если она имеет три ком- поненты расщепления, по крайней мере одна из которых является путем, или такие две, ни одна из которых не является путем (рис. 5.34). Алгоритм 5.8. Проверки существования выпуклого изображения Дано. Граф G. Требуется. Да или нет в зависимости от того, есть у G плоское выпуклое изобра- жение или нет, а также само плоское изображение графа G, если оно существует. Метод. функ nPOBEPKA(G) = 1. Находятся все разделяющие пары для G путем применения линейного алгоритма Хопкрофта—Тарьяна нахождения 3-связных компонент графа; 2. Пусть F — множество FCP и С — множество CSP; 3. если F * 0 то возврат "нет" иначе
Глава 5. Визуализация 377 4. если С = 0 то 5. Строится выпуклое изображение G с помощью описанного 6. ранее алгоритма, где S —любой цикл грани G; 7 возврат "да" 8. иначе если |С| = 1 то 9 Выбирается в качестве S цикл с CSP на нем, и строится выпуклое представление G; 10 возврат "да" 11. иначе Преобразуется каждая CSP с тремя компонентами расщепления путем удаления той компоненты, которая является путем. Затем соединяются все пары вершин в С с новой вершиной Vs и проверяется, является ли результирующей граф G'планарным 12. • если G' не планарный то возврат "нет" 13. иначе Пусть Z— плоское изображение графа G'; 14 Пусть S — граница грани, которая объемлет вершину Vs в Z после удаления всех ребер, инцидентных Vs. 15. Строится выпуклое изображение G с границей S; 16 возврат "да" все все все все все 5.2 .7. Методы, основанные на канонических упорядочениях Существует целый ряд методов укладки планарных графов, которые опираются на специальные упорядочения вершин, часто называемые каноническими. В этих алго- ритмах сначала вершины упорядочиваются, а затем по одной (или группами) верши- ны последовательно добавляются в соответствии с найденной упорядоченностью к структуре данных, описывающей представление графа. Используемые упорядочения и сами алгоритмы имеют ряд общих следующих свойств. Упорядочение вершин определяется посредством некоторого расположения графа 2. Упорядочение вершин графа определяет упорядоченное разбиение всех его вер- шин Ина попарно непересекающиеся непустые подмножества И, И2, Vk. 3. На шаге i исполнения алгоритма вершины из Г', вместе с ребрами, их соединяю- щими между собой и с вершинами из И, и И2 kJ...и , добавляются к структуре данных, определяющей представление графа.
378 Часть I. Обработка и визуализация графов 4. Множество V, содержит соседние вершины и, таким образом, в подграфе, порож- денном представления £>,. есть одно ребро, которое лежит на границе внешней грани каждого 5. Пусть S, обозначает структуру данных после добавления вершин и пусть £),— соответствующее ей представление графа. Тогда D, является представлением дву- связного графа, все вершины которого, смежные вершинам из K/+l при- надлежат внешней грани представления. (Существуют алгоритмы, в которых дан- ное свойство нарушается). К классу данных методов относится следующий алгоритм Фраузенха—Паша—Пол- лака построения плоских сетчатых триангуляций в области размера (2и время О(п log и), где п — число вершин графа. 4)х(и 2) за Пусть G = (K,E) — внешней грани. Пусть л триангуляция плоской укладкой D, где (р, Я) е Е лежит во нумерация вершин G, в которой л(р) С,— подграф, порожденный множеством {р е V : л(р)<г}, а С,- — 1 и л (<у) = п. Пусть внешняя грань представления Д графа G,, получаемого из D удалением представлений всех элемен- тов, которые не принадлежат G,. с Тогда л определяет каноническое упорядочение вершин G, если для любого i, 4 < i < п справедливы следующие свойства: П подграф Grl является двусвязным и C,_j содержит ребро (л(1), л(2)); □ в представлении D вершина л(г) лежит во внешней грани графа G,_| и ее соседи в G,_j образуют подинтервал границы G,„[, содержащий по крайней мере два эле- мента. Такое каноническое упорядочение существует для любой плоской триангуляции графа, и оно может быть вычислено за линейное время, начиная с представления D, путем последовательного удаления по одной вершине из внешней грани, которая не является инцидентной ни одной хорде внешней грани (очевидно, что такая вершина всегда существует для любой плоской триангуляции). Инвариантами алгоритма реального рисования графа являются следующие свойства, справедливые после шага i, связанного с вставкой вершины i и соответствующих ребер: □ вершина л (1) размещена в позиции (0, 0), а л (2) — в позиции (2/ - 4,0) ; □ если последовательность вершин внешней грани имеет вид с(, с2, ..., ск, где су = л(1) и ск = л(2), то х(с}) < x(cj +1) для всех j, 1 < j < к; □ ребро (су,Су+1) имеет уклон +1 или -1 для всех j, 1 < j < к. Для того чтобы описать идею алгоритма рисования, определим левую вершину с( вершины л (г), как самую левую вершину из С,_|, которая соединена ребром с л(/). Под самой левой мы понимаем ту, которая встречается первой на пути по.С;_| из л(1) к л (2) не по ребру (л(1), л (2)). Правая вершина сг вершины л(0 определяется, как самая правая вершина из С;_|, которая соединена ребром с л(/). Пусть далее q+i обо- значает вершину С/_|, расположенную непосредственно справа от вершины с/.
Глава 5. Визуализация 379 Когда требуется добавить вершину тг(/), мы сдвигаем вершины с/+1 к cr..j на одну еди- ницу вправо и сдвигаем вершины сг и с* на две единицы вправо. Мы также должны сдвинуть некоторые внутренние вершины представления графа вправо, чтобы гаран- тировать, что представление остается плоским. Это достигается запоминанием для каждой вершины р. из С, множества зависимых вершин, которые должны переме- щаться в параллель с р. Когда р удаляется из границы внешней грани, мы добавляем р к ее собственному списку зависимых вершин и делаем подходящее изменение спи- ска множества зависимых вершин новой вершины на внешней грани. Вершина л(/) размещается на пересечении линии с уклоном +1, исходящей из с„ плинии с уклоном - 1, исходящей из сг. На рис. 5.35 изображен пример построения представления графа алгоритмом Фраузейха—- Паша— Поллака. Такой подход мо- жет также применяться к нетриангулированным графам путем предварительного до- бавления ребер, чтобы сделать граф триангулированным, затем применяя алгоритм и удаляя добавленные ребра в вычисленном представлении. Рис. 5.35. Пример работы алгоритма Фраузейха — Паша — Поллака 5.3. Поуровневое рисование ориентированных графов Далее мы сконцентрируем свое внимание на изображении ациклических орграфов (дэгов). Выбор этого подкласса для рисования можно объяснить двумя причинами. Во-первых, преимущественное большинство реальных графов, встречающихся в про- граммировании, являются ациклическими, а, во-вторых, любой ориентированный (и тем более неориентированный) граф может быть преобразован к ациклическому орграфу путем смены или задания ориентации у части его ребер (см. разд. 5.3.5). Наиболее известный подход к размещению ациклических орграфов является обоб- щением стандартного подхода, используемого для размещения деревьев. Для под- черкивания иерархичности структуры дэга при его укладке строятся, как и в древес- ном случае, поуровневые представления, в которых все дуги графа следуют одному нтому же направлению. Такие представления называются монотонными поуровне- ' выми представлениями.
380 Часть I. Обработка и визуализация графов Отличительной чертой методологии поуровневого представления является ее интуи- тивная понятность и масштабируемость. Под масштабируемостью мы здесь понима- ем разделение методологии на ряд малопересекающихся задач. Любая конкретная реализация — это всегда конструктор, т. е. набор методов, решающих задачи разных этапов. Собирая такой конструктор, исследователь должен выбрать сбалансирован- ный набор методов. Такой набор должен быть непротиворечивым по целям и эквива- лентным в терминах временной сложности. Если в набор входит алгоритм, имеющий квадратичную сложность, то нет смысла "экономить" на решении задач других эта- пов, применяя к ним линейные, но "плохие" эвристики. Методы, основанные на поуровневом размещении (иерархический подход), хотя и не являются лидерами по всем эстетическим критериям, однако значительно опережают конкурентов на больших графах, возникших в реальных приложениях. 5.3.1. Общая схема поуровневого подхода При размещении ациклических графов во внимание принимаются следующие эсте- тические критерии: □ совпадающее направление ребер; □ минимизация площади изображения; □ равномерность распределения вершин по площади всего изображения; □ отсутствие слишком длинных ребер; □ минимизация количества пересечения ребер; □ прямолинейность ребер. Одновременная оптимизация всех перечисленных критериев является невозможной потому, что эти критерии зачастую оказываются противоречащими друг другу. Так, например, условие прямолинейности ребер нарушает равномерность распределения вершин и увеличивает общую площадь изображения. Существует несколько различных техник размещения ациклических графов. Каждая из этих техник ставит во главу угла один или несколько из перечисленных эстети- ческих критериев и старается в меру возможностей удовлетворить оставшиеся кри- терии. Например, можно решать задачу размещения ациклических графов сведением их к планарному графу и дальнейшему построению выпуклого изображения, используя особенности топологии планарных графов, с последующим восстановлением изна- чальной структуры. Так, например, хорошо изучена задача построения выпуклого изображения для планарных ациклических ^/-графов, т. е. графов, имеющих одну входную и одну выходную вершины, а также планарную укладку, в которой дуга, соединяющая эти вершины, лежит во внешней грани. Они допускают монотонное изображение с прямолинейными ребрами, внешняя грань которого есть заданный треугольник. Изображение в этом случае строится рекурсивно, путем выделения спе- циальным образом ^-подграфов с меньшим множеством вершин, чем у исходного, и применения алгоритма к ним. При таком подходе, когда фиксируется внешняя грань и дуги изображены прямыми линиями, с возрастанием степеней вершин углы между
Глава 5. Визуализация 381 смежными ребрами быстро уменьшаются, что сильно понижает читаемость изобра- жения. Существует общий метод сведения произвольного планарного ациклического графа к «-графу с сохранением планарности, однако, само требование планарности исходного графа является слишком жестким. С одной стороны, задача удаления ми- нимального количества ребер произвольного ациклического графа так, чтобы сделать граф планарным, является УР-трудной, а с другой — не слишком подходит нашим целям, поскольку нарушает саму структуру исходного графа. Задачу автоматического размещения ациклических графов можно также решать с помощью ортогональных техник, которые широко используются для графов произ- вольного вида и имеют хорошие временные показатели Основным недостатком дан- ного подхода является то, что теряется возможность отражения иерархичности графа, к тому же размещения, полученные с использованием ортогонального подхода, более разряжены, чем, например, плоские размещения, и, соответственно, имеют большую площадь, что понижает удобность изучения структуры графа. Следует отметить так- же то, что при ортогональном подходе при изображении орграфов степени вершин более 4-х возникает проблема с появлением существенного разброса в размерах вер- шин. Дело в том, что у вершины для размещения инцидентных ей ребер, число кото- рых превышает 4, требуется увеличить размер изображения, что может привести к одновременному наличию и слишком больших, и совсем маленьких вершин Для построения изображения дэгов наиболее широко применяется так называемый иерархический подход, который направлен на получение их поуровневого размеще- ния. Данный подход является крайне интуитивным и позволяет для произвольного ациклического орграфа построить монотонное поуровневое представление с ребрами в виде ломаных или сплайнов в процессе последовательного решения следующих грех задач: □ распределение вершин по уровням так, чтобы все дуги следовали одному направ- лению; □ выбор порядка вершин на уровне с целью минимизации пересечений ребер; П определение координат вершин на уровне с целью минимизации общей длины ребер и количества изломов. Таким образом, данный подход позволяет разбить задачу нахождения расположения ациклического графа на три достаточно независимых шага, реализация которых опи- рается на свои методы и использует различные эстетические критерии. Для успешного применения иерархического подхода система изображения графов (исходные данные, визуализирующая компонента, область применения) должна удовлетворять следующим ограничениям: П исходный граф должен быть ациклическим мультиграфом или мультиграфом, "близким" к ациклическому. Близость здесь следует понимать в том смысле, что смена ориентации малого количества дуг должна превратить граф в ацикличе- ский; □ семантика графовой информации должна предполагать возможность построения монотонного изображения, подчеркивающего направленность или наличие неко- торого порядка на множестве вершин;
382 Часть I. Обработка и визуализация графов □ система визуализации не должна предполагать проведение только прямолиней- ных ребер между вершинами графа. Ребра должны быть изображены в виде ло- манных или сплайнов. Рис. 5.36. Этапы построения поуровневого изображения Канонически метод поуровневого изображения состоит из трех последовательно применяющихся шагов,-которые изображены на рис. 5.36. 1 . Распределение вершин по уровням. Каждой вершине и присваивается число Ци), указывающее уровень этой вершины, так, чтобы все дуги, соединяющие вершины, следовали от меньшего номера к большему, при этом вершины одного уровня не должны быть связаны между собой. Подразумевается, что все вершины одного уровня будут расположены на одной прямой — вертикальной или горизонталь- ной — в зависимости от того, какое мы предпочитаем общее направление разме- щения: сверху вниз или слева направо. После проведения распределения вершин по уровням просматриваются все дуги: если дуга е = (и, v) проходит через не- сколько уровней, т. е. L(u) — L(y)> 1, то она удаляется из графа и заменяется на
Глава 5. Визуализация 383 цепочку фиктивных вершин vb такую, что V! = и, vN = и, каждая вершина v, соединена дугой с v/+1 и L(y, t) = A(v,) + 1, a V| = v и vN- и. 2 . Определение порядка вершин науровне. Задача данного шага состоит в сортировке вершин на каждом из уровней. Порядок вершин определяет топологию конечного изображения и должен быть выбран с целью минимизации пересечений ребер графа. 3 . Определение координат вершин на уровне. На данном шаге каждой вершине при- сваивается вертикальная координата (при размещении в горизонтальном направ- лении) так, чтобы сохранить порядок вершин на уровне, который был вычислен на предыдущем шаге. Координата выбирается с целью минимизации общей дли- ны ребер и количества изломов. Наконец, конечное изображение получается представлением каждого ребра в виде прямолинейного отрезка и удаления фик- тивных вершин. В этом случае длинные ребра оказываются изображенными в ви- де ломанных. Некоторые исследователи склонны выделять задачу проведения ребер в отдельный этап алгоритма. Это целесообразно делать, если ребра изображаются не канониче- скими ломаными, а, например, сплайнами Существуют эффективные методы прове- дения сплайнов, не пересекающих вершины графа и проходящих через заданные об- ласти плоскости. Также задача проведения ребер выделяется в отдельный этап, если вершины графа имеют неточечное представление. При этом приходится следить за отсутствием пе- ресечений ребер и вершин графа, а также определять точки на изображении верши- ны, в которые будут входить и выходить ребра, инцидентные этой вершине графа. Как уже было сказано (см. разд. 5.3), в случае, когда исходный граф не является ациклическим, требуется отдельный шаг алгоритма, который отвечает за препроцес- сирование графа и преобразование его к ациклическому ориентированному графу. После построения изображения структура изначального графа восстанавливается Иерархический подход оказывается не очень удачным с точки зрения построения инкрементального размещения. Этот факт можно объяснить тем, что топология по- лучаемого изображения очень сильно зависит от выделенной на первом шаге алго- ритма иерархии вершин. А даже при локальных изменениях графа, как-то: удаление пли добавление вершин, групп вершин или ребер — не удается сохранить эту иерар- хию неизменной. Вопросы инкрементального размещения очень тесно переплетены с вопросом удовлетворения ограничений на получаемое изображение. В качестве ог- раничений, которые могут быть удовлетворены при таком подходе, можно назвать требование разместить две выделенные вершины с одного уровня иерархии как мож- но ближе друг к другу, а также выравнивание вертикальных координат вершин с раз- ных уровней иерархии. Иерархический подход размещает граф по уровням, образуя монотонное изображе- ние. Направление следования уровней может быть как горизонтальным, так и верти- кальным. В реальных системах это должно определяться семантикой изображаемой информации. Так, например, для иерархий классов более привычной является верти- кальная укладка, для графов вызовов — горизонтальная. Иногда в данном вопросе
384 Часть I. Обработка и визуализация графов решающее значение играет визуализирующая компонента или какие-либо ограниче- ния системы. При горизонтальной укладке преимущественным направлением дуг является горизонтальное, что позволяет размещать на них длинные надписи, поэтому в дальнейшем будем считать, что уровни размещаются слева направо. 5.3.2. Распределение вершин по уровням Задачей данного шага является присваивание каждой вершине ее конечной горизон- тальной координаты. Для этого исходный ациклический граф G = (И, Е) должен быть приведен к поуроенееому ациклическому графу. Поуровневое разбиение есть разде- ление V на подмножества £ь £2, > L/п та1< что для каждого ребра (г/, v) е Е, где и е £, и v е £;, верно то, что г > j. Высотой разбиения будем называть количество уровней И, а шириной w — число вершин на самом большом уровне. Зазором ребра {и, г), где и е £, и v £ Lj, называется разность i—j. Разбиение называется сжатым, если не су- ществует ребра с зазором, большим единицы. После разбиения вершин по уровням всем вершинам одного уровня присваивается одна горизонтальная координата, т. е. = i для всех вершин с уровня £,. \ Техника фиктивных вершин Существование поуровневого распределения для ациклических графов очевидно Однако не для всякого ациклического графа существует его сжатое разбиение — это может быть продемонстрировано уже для графа, состоящего всего из трех вершин (рис. 5.37). Необходимость же построения сжатого разбиения диктуется следующими двумя причинами. Во-первых, сжатое разбиение минимизирует горизонтальную дли- ну ребер и количество их изломов. При сжатом разбиении ребра связывают вершины только соседних уровней и могут быть изображены прямолинейными отрезками. Во- вторых, сжатое разбиение существенно упрощает задачу минимизации пересечений ребер графа, которая решается гга втором шаге алгоритма. Сжатое разбиение сводит эту глобальную задачу к задаче минимизации пересечений для двух соседних уров- ней. Рис. 5.37. Пример графа, не имеющего сжатого изображения Для построения сжатого разбиения произвольного ациклического графа применя- ется техника вставки фиктивных вершин (рис. 5.38). Фиктивные вершины добавля- ются в граф вдоль длинных ребер, т. е. ребер с зазором, большим единицы. Для каж- дого такого ребра (и, г), и е £, и v е Ljс зазором £ = i-j> 1 добавляется k - 1 вершин uh ... ик |, такие, что ит е £, Такое построение приводит к тому, что в графе остаются только ребра, соединяющие вершины соседних уровней, и задача минимизации пересечения ребер сводится к
Глава 5. Визуализация 385 соответствующей задаче для двухуровневого случая. Данное построение заодно ре- шает и задачу проведения ребер в конечном изображении. Ребро изображается в виде ломанной, концами которой являются сами вершины, а точками излома — вставлен- ные на первом этапе фиктивные вершины. Таким образом, исчезает возможность пересечения ребер с вершинами. Заметим здесь, что существуют варианты поуровневого размещения ациклических орграфов, которые не используют технику фиктивных вершин, но вынужденно уде- ляют дополнительное внимание вопросу проведения ребер графа. Рис. 5.38. Вставка фиктивных вершин Критерии построения разбиения Можно сформулировать набор критериев, которые стоит принимать во внимание при построении поуровневого разбиения. Во-первых, искомое размещение графа должно быть компактным. Поскольку пло- щадь фактически зависит только от количества уровней и максимального количества вершин на одном уровне, то компактизации можно добиться уменьшением одной из этих величин. При этом высота графа оказывается ограниченной снизу длиной мак- симального пути в графе. Существуют простые методы, позволяющие достичь ниж- ней оценки на высоту разбиения, однако минимизация ширины есть Л'Л-трудная за- дача, которая в реальных системах может быть решена только приближенно В связи с этим различием необходимо заметить, что предпочтение выбора величины для ми- нимизации зачастую определяется на уровне визуализирующей системы. Если вер- шины графа изображаются не просто точками, а областями на плоскости, причем имеющими некоторые текстовые надписи, то при горизонтальной укладке наиболее важной становится высота разбиения, а при вертикальной — ширина. Это может быть еще одним хорошим доводом для использования горизонтального следования уровней в изображении графа. Следующий важный критерий к разбиению вершин— это минимизация количества фиктивных вершин. Такое желание связано с тем, что введение фиктивных вершин повышает общую сложность алгоритма. Если мы рассматриваем достаточно плотный граф, в котором длинных ребер O(N), то после их удаления мы получим О(№) фик- тивных вершин. Немаловажно также и то, что чем больше мы вводим фиктивных вершин, тем больше получится в конечном размещении изломов на дугах. Таким об- разом, кроме минимизации общего числа вершин необходимо минимизировать мак- симальную длину ребра, т. е. число фиктивных вершин, заменяющих одну дугу, по- тому как чем длиннее ребро и чем больше на нем изломов, тем сложнее при изучении изображения проследить соответствующую связь в графе. Ну и поскольку сложность всех шагов алгоритма размещения графа зависит от общего количества вершин, то 13 Зак. 202
386 Часть I. Обработка и визуализация графов мы должны стремиться к тому, чтобы не слишком увеличить это количество при до- бавлении фиктивных вершин. К сожалению, одновременная минимизация высоты разбиения и количества фиктивных вершин уже оказывается /VP-трудной задачей. Поуровневое размещение иногда должно учитывать ограничения, налагаемые семан- тикой исходного графа. Так, в некоторых приложениях часть вершин оказывается предраспределенной по уровням. Это предраспределение может быть вызвано жела- нием выделить некоторые вершины или явно указать последовательность появления вершин (time-lines). Чаще всего такая задача может быть сведена к исходной путем предварительного слияния вершин с одинаковым предопределенным рангом. Распределение по длиннейшему пути Данный способ позволяет за линейное время распределить вершины графа по уров- ням так, чтобы высота получающегося разбиения оказалась минимальной. Для этого надо поместить все стоки (вершины без выходящих дуг) на уровень £ь а каждую ос- тавшуюся вершину — на уровень Lp, н где р — длина наибольшего пути от этой вер- шины до ближайшего стока. Следует отметить, что данный способ построения разбиения является инвариантным относительно направления дуг. При построении разбиения от стоков мы получим граф со всеми стоками, расположенными на одном уровне, но аналогичным образом разбиение можно построить и от источников (вершин без входящих дуг), и при этом все источники будут расположены на одном уровне. Очевидно, что высота обоих разбиений будет одинакова, однако ширина может отличаться на сколь угодно боль- шую величину (рис. 5.39). Поскольку данный алгоритм является линейным, то пред- ставляется разумным построить оба разбиения и выбрать из них наименее широкое. Основной недостаток распределения по длиннейшему пути — это отсутствие опти- мизации на ширину разбиения. Рис. 5.39. Два способа распределения по методу длиннейшего пути
Глава 5. Визуализация 387 Минимизация ширины разбиения К сожалению, задача нахождения разбиения с минимальной шириной и при этом с ограниченной высотой является ЛТ’-полной М’-полнота задачи следует из сведения к ней известной /VP-полной задачи составления расписания для мультипроцессора. Каждая вершина ациклического графа может представлять работу, которая может быть выполнена на любом из процессоров за единичное время. Ребро графа пред- ставляет ограничение предшествования на выполняющиеся работы. Составление расписания для мультипроцессора есть распределение работ по W процессорам так, чтобы все они могли быть выполнены за время, не превосходящее Н. Понятно, что такое расписание существует, если есть разбиение графа по уровням с высотой, не большей Н, и шириной, не большей W. Эквивалентность задачи поуровневого разбиения задаче составления расписания для мультипроцессора позволяет сразу же воспользоваться результатами, достигнутыми в этой области. Существует ряд эвристик для решения задачи составления расписа- ния. и эти эвристики могут быть применены к нашей задаче. Например, известная эвристика Кофман—Графама позволяет построить разбиение ширины W, и при этом его высота не будет превосходить (2 — 2/W)hm\a, где /zmin— минимально возможная высота разбиения шириной W. Стоит заметить, что минимизируемая данными способами ширина разбиения может оказаться все равно неудовлетворительной, поскольку алгоритм не учитывает после- дующую вставку фиктивных вершин. В полученном графе могут оказаться уровни с огромным количеством ребер, идущих через них, и эти ребра будут заменены фик- тивными вершинами, что расширит такие уровни. Однако, учитывая то, что в конеч- ном изображении графа фиктивные вершины будут образно заменены ребрами, мож- но сказать, что данный способ построения разбиения является вполне приемлемым, если ширина дуг графа мала по сравнению с размерами вершин. В противном случае предлагаются модификации эвристики Кофман-Графама, учитывающие ширину, "приносимую" фиктивными вершинами. Минимизация количества фиктивных вершин Существует полиномиальный алгоритм, позволяющий построить разбиение с мини- мальным количеством фиктивных вершин. Нахождение оптимального разбиения можно сформулировать в виде задачи линейного целочисленного программирования: min £ Ьи - Lv, где (и, v) — ребро с ограничениями: Llf— Lv> 1 и Lu, Lv > 1. (u,v)e£' I Существует ряд способов решения данной задачи за полиномиальное время. Пер- I вый - решить эквивалентную линейную задачу, а затем за полиномиальное время I трансформировать решение в целочисленное. Другой способ — это сведение данной I задачи к задаче минимизации потоков в сети, для которой существуют полиномиаль- I ные решения. Поскольку в такой постановке матрица ограничений является унимо- I дулярной, то для решения может быть применен симплекс метод, который хотя и не I полиномиален, но на практике является быстросходящимся.
388 Часть I. Обработка и визуализация графов 5.3.3. Определение порядка вершин на уровне После построения поуровневого разбиения встает задача определения порядка рас- положения вершин на каждом уровне нашего графа. Нахождение такого распределе- ния с целью минимизации количества пересечения ребер и есть задача данного этапа алгоритма. В первую очередь стоит отметить, что количество пересечения ребер в поуровневом графе не зависит от конечных координат вершин, а зависит только от их относитель- ного положения внутри каждого уровня. Таким образом, задача данного этапа явля- ется не геометрической, а всего лишь комбинаторной. Однако эта задача являет- ся NP-полной уже для графа, имеющего всего лишь два уровня, и, более того, NP-полной эта задача остается, даже если есть всего лишь одна вершина со степе- нью, большей единицы на каждом из уровней. Задачу минимизации пересечений ребер, как в случае двух уровней, так и глобаль- ную, можно естественным образом сформулировать в виде задачи целочисленного программирования. Однако, несмотря на возможность при использовании такой формулировки получения точного решения исходной задачи, такой подход может быть применен только для очень маленьких графов. Практические реализации пока- зывают, что в разумное время решение задачи может быть найдено лишь для графов, содержащих не более 15 вершин (в случае глобальной оптимизации) и не более 60 вершин для каждого из уровней (в случае минимизации пересечений лишь для двух соседних уровней). В абсолютном большинстве работ проблема минимизации пересечений ребер в по- уровневом орграфе решается не глобально для всего графа, а лишь локально — для всех пар соседних уровней. Эксперименты показывают, что сведение задачи миними- зации пересечений ребер к случаю двух уровней дает результаты, очень далекие от оптимальных. Более приемлемых результатов минимизации глобального количества пересечений добиваются путем многократного "просматривания" всех соседних уровней и минимизации пересечений на них Такая эвристика имеет несколько мо- дификаций, которые различаются по: □ выбору способа фиксации уровней. При рассмотрении двух смежных уровней по- ложение вершин на одном из уровней можно считать фиксированным и выбирать оптимальное расположение вершин другого уровня. Возможно также фиксирова- ние положения вершин уровней £,+1 при рассмотрении уровня □ выбору порядка, в котором просматриваются пары соседних уровней. Уровни могут просматриваться слева направо или наоборот, возможно также чередование направлений просмотра; □ выбору критериев окончания просмотров. Это может быть фиксированное коли- чество просмотров или же просмотры делаются, пока они уменьшают или суще- ственно уменьшают общее количество пересечений. Отдельно стоит вопрос о выборе первоначального порядка вершин на каждом из уровней. Традиционно для этого применяется метод, позволяющий избежать пересе- чения ребер в случае, если исходный граф был деревом. Метод состоит в проведении поиска в глубину, при котором вершины получают номера на своем уровне в порядке их просмотра в ходе такого поиска.
Глава 5. Визуализация 389 Существует ряд методов, позволяющих решать задачу минимизации количества пе- ресечений для двух уровней. Пусть имеется двудольный граф G = (Lt, L2, Е), где Z.1 — множество вершин первого уровня, L2— вершины второго уровня, Е— множество ребер. На основе фиксиро- ванного расположения вершин на первом уровне строится расположение вершин на втором уровне. Как уже было сказано, данная задача является NP-полной, и для на- хождения ее приближенного решения используются следующие эвристики. Методы, основанные на сортировке Данная группа эвристик основана на идее сортировки вершин уровня L2 так, чтобы уменьшить количество пересечений ребер. Легко видеть, что для двух выбранных вершин w е Ь2 и v е Ь2 количество взаимопересечений инцидентных им ребер зави- сит только от относительного расположения этих двух вершин на уровне L2 и не за- висит от расположения всех остальных вершин этого уровня. Таким образом, между вершинами одного уровня можно установить отношение/порядок, определяемое ко- личеством пересечений ребер, порождаемых в различных конфигурациях располо- жения вершин. Понятно, что заданное таким образом отношение не может образовывать отношение линейного или частичного порядка. В противном случае обычная сортировка вершин решила бы нашу TVP-полную задачу по крайней мере за квадратичное время. Иллю- стрирует данное замечание следующий пример. На рис. 5.40 изображены два уровня иерархии с целью определения набора отношений между вершинами А, В и С. Легко видеть, что А < В, поскольку при расположении вершины А левее вершины В получа- ется меньше пересечений ребер (одно против двух), В = С (одно пересечение в любом из случаев), но, в свою очередь, С < А (три пересечения против четырех). Получив- шаяся цепочка А < В = С < А показывает, что заданное таким образом отношение не является транзитивным. Рис. 5.40. Расположение вершин на двух соседних уровнях Однако закон трихотомии (для пары (А, В) справедливо одно и только одно из соот- ношений А < В, А = В, А> В) для нашего отношения выполняется. А это означает, что возможна устойчивая сортировка вершин, т. е. сортировка, при которой выполняются условия упорядоченности и устойчивости. Выполнение такого упорядочивания и составляет суть методов, основанных на сор- тировке. Такие методы должны быстро считать потенциальное количество пересече- ний. Это может быть сделано напрямую за О(|£|2), а незначительными усилиями
390 Часть I. Обработка и визуализация графов убыстрено до О(2С„ „), где С„ „— количество пересечений, образуемое парой вершин и и v. Подобный подсчет возможных пересечений для каждой пары нужно выполнить лишь один раз — это и задаст порядок на множестве вершин. Дальнейшая сортиров- ка не изменит установившихся между вершинами отношений. Первый из таких алгоритмов похож по своей идее на метод пузырька. Предлагается просматривать поочередно все пары соседних вершин и менять их местами, если при этом уменьшается количество пересечений. Процесс заканчивается, когда после оче- редного полного просмотра всех вершин второго уровня количество пересечений не уменьшилось (неупорядоченная пара не была найдена). Сложность данного алгорит- ма— O(|Z,2|’)> т. к. Для конечного упорядочивания может потребоваться вплоть до |£2| просмотров. Результат работы такого алгоритма сильно зависит от выбора на- чального расположения, т. к. оперирует перестановками только в терминах соседних вершин. Другой метод, позволяющий упорядочить множество вершин, основан на идее быст- рой сортировки. Сначала выбирается "средняя" вершина, а все остальные вершины разбиваются на два множества в зависимости от того, в каком отношении они нахо- дятся с выбранной вершиной. Затем подобная процедура рекурсивно применяется к каждому из получившихся множеств. В худшем случае временная сложность данно- го алгоритма так же, как и алгоритма быстрой сортировки, является квадратичной, однако в среднем алгоритм требует всего лишь О(Кг| logical) операций. Идея следующего метода тоже использует концепцию сортировки вершин на уровне, хотя явно не прибегает при этом к заранее установленному отношению порядка на множестве вершин. Метод под называнием "отсев" (sifting) на каждом шаге берет одну из вершин и пытается ее вставить в такое место, чтобы породить при этом наи- меньшее количество пересечений ребер. Для этого вершину пытаются последова- тельно вставить в каждое из возможных мест и считают количество получившихся пересечений. Поскольку при сдвиге вершины на одну позицию изменение количества пересечений можно посчитать за константное время (используя предварительно на- копленную информацию), то алгоритм имеет квадратичную временную сложность и по своей сути похож на сортировку вставками. Как уже было замечено, любой основанный на сортировке алгоритм упорядочивания вершин должен работать с набором отношений между парами вершин, и вычисление этих отношений не может быть выполнено за линейное время. Поэтому любой из упомянутых методов будет тоже иметь нелинейную сложность. Методы барицентров и медиан На практике наиболее широко используются линейные алгоритмы, основанные иа методе барицентров. Координата вершины v е £2 определяется как среднее арифме- тическое координат всех ее связей с уровня Ly. avg(«)= 1 ^хДт), deg(w)„eW(u) где N(u)={v е V: {u, v) е Е}.
Глава 5. Визуализация 391 Если после перестановки координаты каких-либо двух вершин совпадают, то они разносятся на минимальное расстояние, порядок при.этом определяется произвольно. Самая распространенная модификация этого метода— метод медиан, где вместо среднего арифметического используется координата среднего соседа с уровня Lh т. е. если щ, и2,..., um eLt — вершины смежные v, причем x1(w1) < xi(w2) < ... < x((wm), то- гда координата x2(v) = med(v) определяется как x((wavg), где avg = l_wZ2_|. В случае, ко- гда med(v) = med(w) и v имеет нечетную степень, а и — четную, то v ставится перед и; если же четность степеней совпадает, то порядок выбирается произвольно. Для каж- дой вершины и значение ее медианы может быть найдено за время G(|A'(w)|), что делает эту эвристику настолько же быстрой, как и метод барицентров. Пусть opt(G, х() — минимально возможное число пересечений ребер для данного графа, где Xi — расположение вершин avg(G, Х|) — число пересечений, остаю- щихся после применения метода барицентров, med(G, Xi) — число пересечений, ос- тающихся после применения метода медиан. А. Если для данного графа G возможно размещение без пересечения ребер, то и ме- тод медиан, и метод барицентров его находят, т. е. если размещение х( такое, что opt(G, Xi) = 0, тогда avg(G, Х|) = med(G, Xi) = 0. Б. Для любого п существует двудольный граф G = (£ь Л2, £), где |Л|| = п, |Л2| = 2, «размещение Xi вершин L} такие, что avg(G, xJ/opftG, Xi) пропорционально п/г. Ъ.Дпя любого п существует двудольный граф G' = (L\, L£ Е7), где |Lf| = п, \L2 | = 2, «размещение х\ вершин £1 такие, что med(G' xi)/opt(G' х'|) > 3 — О(1/и). Г. Для двудольного графа G = (£ь L2, Е) и любого размещения Xi вершин L\ верно не- равенство med(G' xj) < 2 • opt(G' xj), если все вершины L2 не имеют более трех ребер. Известны также следующие модификации метода медиан: П средние медианы, когда для вершин с четной степенью присваивается среднее арифметическое значение позиций вершин с соседнего уровня, и med(w) — для нечетных степеней; П полумедианы, когда для вершин с четной степенью в качестве значения медианы берется значение, полученное по методу барицентров; П взвешенные медианы, когда происходит уточнение метода средних медиан в слу- чае вершин с четной степенью, большей двух. В этом случае взвешенная медиана определяется как ,, Л (v7/2 ) right+xl(v /2+1)-left vmed(w)=---------------------------, left+right где left = xi(vy/2) — X|(v() и right = xi(v7) — xi(v7/2+i). Такая стратегия сдвигает верши- ны к той стороне, где ее соседи располагаются наиболее плотно.
392 Часть I. Обработка и визуализация Переход к планарному графу Альтернативный подход— это замена задачи отыскания перестановки вершин с целью минимизации пересечений ребер на задачу нахождения планарного двух- уровневого ациклического графа. При таком подходе сначала происходит удаление минимального количества ребер, так чтобы полученный после этого двухуровневый граф стал планарным, затем строится плоское изображение полученного графа и до- бавляются к этому изображению удаленные ребра. Понятно, что найденная таким способом перестановка вершин формально не решает задачу минимизации количества пересечений ребер, однако интуитивно ясно, что полученное количество пересечений должно быть близко к минимально возможному. Причем такой алгоритм будет гарантировать достижение абсолютного оптимума в том случае, когда исходный двухуровневый граф допускает плоскую двухуровне- вую укладку. Аргументация такого подхода состоит в том, что визуальное восприятие запутанно- сти графа и количества пересечений ребер зависит не только от самого числа пересе- чений, а так же и от их взаимного расположения. Авторы подхода утверждают, что полученные таким образом представления выглядят зачастую даже лучше, чем пред- ставления, имеющие действительно минимальное количество пересечений ребер. Несмотря на NP-полноту задачи в такой постановке (в силу NP-полноты задачи ми- нимизации удаляемых дуг при получении планарного двухуровневого графа), ее не- сомненным преимуществом перед задачей минимизации пересечений является нали- чие хороших эвристик для нахождения решения с гарантированной оценкой худшего случая. Сама задача нахождения минимального числа дуг для нахождения планарно- го двухуровневого ациклического графа естественным образом формулируется в ви- де задачи линейного целочисленного программирования, позволяя для небольших графов находить ее точное решение. Другие эвристики расположения вершин на втором уровне Вероятностная эвристика. Суть алгоритма заключается в "жадной" вставке всршии на основе предварительно подсчитанной для каждой вершины вероятности образова- ния пересечений. Такая вероятность определяется суммой пересечений для каждого из ребер, инцидентных данной вершине, в полном двудольном графе. Алгоритм Тутти состоит в предварительном определении позиций вершин на двух крайних уровнях с последующим решением системы разряженных линейных уравне- ний *(ц)% J / л Е л'(л>)+— ,1 ; Ex<w) 2outdeg(«)^(|<) 2indeg(M)^A, (н) для определения координат вершин на всех промежуточных уровнях. Назначения. Данная эвристика позволяет свести задачу к известной задаче о назначе- ниях. Для каждой вершины определяется число как верхняя оценка количества пересечений, образованных ребрами, инцидентными вершине I, в том случае, если вершину поместить на место j. Как и в вероятностной эвристике, вычисляются путем дополнения графа до полного. Далее для матрицы D = (<7,;) решается задачао
Глава 5. Визуализация 393 назначениях, т. е. выбираются и элементов так, чтобы покрыть ими каждую колонку и каждый столбец матрицы и при этом минимизировать сумму их значений. Генетический алгоритм. Можно сконструировать генетический алгоритм для двух- уровневой задачи минимизации пересечений. Проведенное сравнение с барицентри- ческим методом показало, что такой алгоритм дает, как правило, лучшие решения, но является крайне медленным Выбор метода Проведенное рядом исследователей сравнение различных методов минимизации пе- ресечений позволяет дать следующие рекомендации по практическому выбору мето- да решения этой задачи. Во-первых, для графов с малой насыщенностью и малым количеством вершин воз- можен поиск оптимального решения за приемлемое время. В этих целях используют- ся методы целочисленного программирования. Симплекс метод, используемый для решения этой задачи, хоть и не имеет гарантированной полиномиальной сходимости, однако на практике оказывается весьма эффективным. С другой стороны, для насыщенных графов минимальное число пересечений ребер очень близко к максимальному. Поэтому, начиная с некоторой степени насыщенно- сти, представляется разумным отбросить все методы поиска наилучшего расположе- ния вершин и вместо этого взять случайное расположение. Таким образом, простор для применения эвристик возникает лишь в "средних" слу- чаях. Как видно из приведенных утверждений, метод медиан теоретически выглядит привлекательнее метода барицентров в силу наличия гарантированной верхней оцен- ки числа пересечений. Но на практике оба метода применяются с равным успехом, при этом после использования одного из барицентрических методов разумно приме- нение методов, основанных на сортировке для локальной корректировки и оконча- тельной доводки расположения вершин на уровне. Отдельно стоит задуматься над критериями остановки итерационного эвристическо- го процесса. Чаще всего остановка производится после проведения некоторого, зара- нее определенного, числа итераций, либо после того, как конфигурация вершин пе- рестанет изменяться, либо количество пересечений перестанет уменьшаться. Для методов, основанных на сортировке, выбрать количество необходимых итераций достаточно просто, однако эта величина не может быть разумно предопределена для барицентрических методов. Изменение конфигурации вершин на каждом из шагов алгоритма очень легко отследить в процессе вычислений, но практика показывает, что останов по такому критерию наступает крайне редко. Представленные методы склонны не иметь устойчивых конфигураций вершин. Подсчет количества пересечений на каждом шаге алгоритма кажется самым объек- тивным критерием останова. Проблема заключается в том, чтобы быстро вычислить это количество. Подсчет в лоб может быть произведен лишь за время О(|Е|2). Для методов, основанных на сортировке, такой результат вполне приемлем, поскольку одновременно с подсчетом пересечений может быть выполнено и вычисление отно- шения порядка на множестве вершин. Известен алгоритм, позволяющий вычислить порядок на множестве вершин и количество фактических пересечений за время 0(£ log(E + /0), где К— количество фактических пересечений. По сути же такой ал-
394 Часть I. Обработка и визуализация графов горитм остается квадратичным относительно числа ребер, поскольку в худшем слу- чае количество пересечений квадратично. Представленные квадратичные алгоритмы подсчета количества пересечений не мо- гут быть приемлемыми для линейных барицентрических методов. Однако алгоритмы могут быть существенно убыстрены, если отказаться от одновременного вычисления отношения порядка на множестве вершин. Лучший из известных алгоритмов произ- водит вычисление количества пересечений ребер в двухуровневом графе за время О(Е log(E)), и, по всей видимости, этог результат не может быть существенно улучшен. 5.3.4. Определение координат вершин на уровне После определения порядка вершин на уровне необходимо определить их настоящие вертикальные координаты. Канонически, в иерархическом подходе, ребра графа изо- бражаются в виде ломанных с точками излома, находящимися в фиктивных верши- нах, поэтому задача определения окончательных координат всех вершин одновре- менно является и задачей проведения ребер. Если же ребра графа имеют какую-либо другую форму и/или способ проведения, то соответствующие критерии должны быть рассмотрены при решении задачи о постановке вершин Точное решение В случае изображения ребер в виде ломанных задача определения окончательных координат вершин решается из соображений минимизации числа изломов в прово- димых затем ребрах. При этом должен быть учтен и не нарушен порядок следования вершин на каждом из уровней. В такой постановке задача формализуется следующим образом. Пусть у нас есть путь p = (vi,V2, v*), в котором вершины v2, v3, ..., v* । являются фиктивными. Если бы такой путь был изображен прямолинейным отрез- ком, то для i от 2 до к - 1 должно выполняться равенство углов наклона отрезков ло- маной y(v,) - y(v,) = ) - y(vi)) к -1 Затем, определяя функцию g(p) как t-i g(p)='ZSy(yl)-al)2, 1=2 ф )-y(v, ))+y(V|), к-1 мы можем попытаться глобально минимизировать суммарное отклонение от прямо- линейности: р учитывая ограничение Xw) — y(z) >= q для всех пар вершин, расположенных на одном уровне так, что вершина w расположена выше вершины z. В этом случае q будет ми- нимально возможным вертикальным расстоянием между вершинами.
Глава 5. Визуализация 395 Функцию для минимизации можно слегка модифицировать, например, так, чтобы отдать предпочтение ортогональным дугам. Для этого надо минимизировать квадрат разности вертикальных координат для всех ребер: (z/,v)eE Также возможно введение дополнительных весов, которые призваны, чтобы рас- прямлять именно длинные ребра— как потенциальных обладателей большого коли- чества изломов: Q(w, v)co(w, v) | y(w) - j(v) I, (w,v)e£ где io(z/, v)— мера важности спрямления ребра (u, v). Q(m, v) — коэффициент для спрямления длинных ребер. Авторы подхода предлагают определить Q(e) следующим образом: О(<?) = 8, если оба конца ребра являются фиктивными вершинами, Q(e) = 2, если только одна из конечных вершин фиктивная, и Q(e) = 1 в остальных случаях. Здесь стоит отметить два существенных отрицательных момента данного способа определения вертикальных координат вершин. Во-первых, решение данной миними- зашюнной задачи с квадратичным относительно количества вершин набором ограни- чений может потребовать существенных временных ресурсов Во-вторых, точное решение с красивыми прямолинейными ребрами может тем не менее оказаться нику- да не годным ввиду чрезмерно разросшейся площади изображения. Для избежания разрастания ширины изображения можно усилить налагаемые на вертикальные ко- ординаты ограничения, однако это лишь увеличит сложность задачи и возможно элиминирует существование точного решения Эвристики Ввиду перечисленных проблем, возникающих при попытках найти точное решение глобальной задачи спрямления ребер, на практике широко применяются эвристиче- ские подходы к решению данной проблемы. Одной из очевидных эвристик является использование идеи барицентров в сочетании с ограничениями на порядок вершин, полученными на предыдущем шаге. Вершины последнего уровня распределяются равномерно на некотором отрезке вертикальной прямой, выделенной под вершины этого уровня. Затем для каждого следующего уровня координаты его вершин последовательно определяются как среднее арифме- тическое координат их соседей из уже поставленных уровней. При этом, как правило, не допускается нарушение изначального порядка вершин на уровне. Существует также набор локальных эвристик, которые применяются к уже расстав- ленным по вертикали вершинам для того, чтобы улучшить общую картину. Такие локальные эвристики, как правило, применяются последовательно до тех пор, пока не достигнет локального минимума некоторая весовая функция, либо не будет со- вершено определенное количество итераций. В качестве оптимизируемой функции может выступать любая глобальная функция, оценивающая общую длину ребер или их общую прямолинейность.
396 Часть I. Обработка и визуализация графов Хорошие результаты могут быть получены применением методов, основаннБ1х на упругосиловой физической модели. В таких алгоритмах положение вершины опреде ляется силами, действующими на нее со стороны других вершин через ребра "пружины" или ребра-"резиновые жгуты". На такую систему накладывается ряд ог раничений, для того чтобы предотвратить чрезмерное сближение вершин и сохране ние предварительно вычисленного порядка вершин на уровне. Для определения окончательных координат на уровне можно использовать метод "маятника", который интерпретирует вершины как грузы, подвешенные на ребра— струны. Далее такая система приходит в движение под действием гравитационного поля, и вершины, тол кая друг друга (но не перескакивая), занимают положение, соответствующее мини- муму потенциальной энергии системы. Стоит отметить, что зачастую алгоритм определения вертикальных координат вер- шин и проведения ребер очень сильно зависит от особенностей визуализирующей системы. Так, существенным может оказаться форма изображаемых вершин, способ "прикрепления" ребер к вершинам, форма ребер и т. д. В этих случаях возможны су- щественные модификации алгоритма определения вертикальных координат вершин. 5.3.5. Предварительные преобразования графа Как уже было сказано (см. разд. 5.3), данная методология может быть применена не только к ациклическим графам, но также к графам, близким к ациклическим, и даже просто к неориентированным графам. В этих случаях, когда структура графа не соот- ветствует нашему изначальному предположению об ацикличности, требуется произ- вести некоторые предварительные преобразования над графом. Суть и цель этих пре- образований заключается в обратимом преобразовании структуры, так чтобы после размещения ациклического графа возможно было безболезненно для качества полу- чаемого изображения восстановить структуру изначального графа и, тем самым, по- строить его изображение. Например, для построения изображения неориентирован- ного графа можно сначала превратить его в дэг, задав ориентацию его дуг. Существует несколько различных подходов к таким преобразованиям. Например, можно предложить склеить каждый из циклов в одну вершину или разместить каж- дый из циклов на одном уровне. Возможна также вставка в цикл дополнительной вершины, которая будет его разрезать. Однако данная группа преобразований суще- ственно изменяет структуру графа, и это, как правило, сильно сказывается на качест- ве получаемого изображения. Это связано с тем, что такие преобразования разруша- ют имеющуюся иерархическую структуру графа. Хорошо известна проблема нахождения минимального множества дуг, разрезающих все циклы, т. е. таких дуг, выкидывание которых из графа сделает его ациклическим. Эта задача является NP-полной, однако для ее решения существуют хорошие линей- ные эвристики. К сожалению, данный метод сведения графа к ациклическому не со- всем применим в случае иерархического подхода. Проблема заключается в том, что после построения изображения графа, которое не учитывает выкинутые на первом этапе ребра, задача проведения таких ребер становится слабо формализуемой и край- не тяжелой. Следующий, общепринятый, подход к обратимому преобразованию структуры графа предлагает "разворачивать" часть ребер вместо "выкидывания" их из графа. Преиму-
Глава 5. Визуализация 397 щество данного способа заключается в том, что развернутые ребра участвуют в по- строении финального изображения наравне с обычными родными ребрами графа. Для этих ребер также решаются задачи спрямления и минимизации пересечений. По- сле построения конечного изображения у развернутых сначала ребер еще раз меняет- ся ориентация. Здесь встает задача отыскания минимального множества ребер графа, разворот которых сделает его ациклическим. Стоит отметить, что, несмотря на ка- жущуюся существенной разницу формулировок, эта проблема эквивалентна пробле- ме отыскания минимального множества дуг, разрезающих все циклы Эквивалент- ность предлагает использовать похожие эвристики для решения и этой задачи. Для упрощения анализа приведенных эвристик будем считать наш граф простым ориентированным графом без мультиребер Для этого в исходном графе следует за- менить мультидуги на ребра с соответствующим весом. Отдельное внимание стоит уделить проблеме придания ориентации для 2-циклов. Если исходный граф содержит 2-циклы, т. е. пары разнонаправленных ребер {(г/, v), (v, г/)}, то предлагается сначала совсем удалить такие ребра, а затем к упрощенному графу применить эвристики для нахождения множества разворачиваемых ребер. После этого ребра, образующие 2-циклы, вставляются в граф и им придается одно и то же направление; такое на- правление всегда можно задать так, чтобы в графе не образовались новые циклы. Наиболее простой и очевидный способ поиска дуг для разворота заключается в вы- делении какого-либо остовного дерева в графе и развороте тех дуг, которые не соот- ветствуют направлению, заданному остовным деревом. В наихудшем случае при этом будет развернуто |Е|-|Е|-1 ребер. Еще один тривиальный метод предлагает вы- брать произвольную нумерацию вершин графа и развернуть те дуги, которые идут от вершин с большими номерами к вершинам с меньшими номерами. Если более поло- вины дуг оказывается выкинутыми, то следует поменять нумерацию на обратную, это гарантирует выкидывание не более |Е|/2 ребер в наихудшем случае. Можно посчитать, сколько раз каждое ребро входит в цикл, и развернуть ребро, по- лучившее наибольшую оценку. Процесс продолжается до образования ациклического графа. К сожалению, в настоящее время нет теоретических оценок для данного ме- тода. Наиболее же часто используемая эвристика носит название "жадного" алгоритма. Алгоритм гарантирует нахождение ациклического подграфа, в котором не менее чем (|£|/2 + | Е|/6) ребер, и если исходный граф не имеет циклов, то алгоритм оставляет его без изменений. Эвристика предлагает найти такую нумерацию вершин, при кото- рой количество ребер, идущих против этой нумерации, минимально (рис. 5.41). На каждом шаге алгоритма из исходного графа выкидывается вершина и получает свой номер. Сначала выкидываются все источники и стоки и получают, соответственно, наименьшие и наибольшие номера. В дальнейшем при отсутствии источников и сто- ков из графа выкидывается вершина с наибольшей разницей количества выходящих и входящих дуг и ей присваивается наименьший из свободных номеров. На каждом шаге алгоритма вместе с удалением вершины удаляются также и все инцидентные ей ребра, таким образом происходит изменение структуры графа. Существует реализа- ция данного алгоритма, имеющая линейную временную сложность. Показано, что для графов, не имеющих вершин со степенью, большей 3, верхняя оценка количества разворачиваемых ребер для данного алгоритма есть (|Е|/3).
398 Часть I. Обработка и визуализация графов Рис. 5.41. Перенумерация вершин при поиске разворачиваемых ребер Используется также эвристика, предложенная Саднером, которая является модифи- кацией рассмотренного "жадного" алгоритма. Она использует другой принцип выбо- ра следующей вершины при отсутствии источников и стоков. Вершина в данном случае выбирается сразу вместе со всей своей сильно связной компонентой. При над- лежащем выборе структур данных такая версия алгоритма будет иметь временную сложность О(|Е|• | И|). Однако, несмотря на впечатляющие практические результаты, теоретическая оценка на количество разворачиваемых ребер так и не была улучшена по сравнению с оригинальной версией алгоритма. Существуют и другие нелинейные эвристики, которые имеют лучшую оценку работы в наихудшем случае. Известно следующее обобщение идеи Сандера. Помимо выбора сильно связных компонент используется тот факт, что для цепочек вершин достато- чен разворот всего лишь одного ребра из цепочки. Стягивание цепочек вершин в ис- ходном графе позволяет для графов, не имеющих вершин степени, большей 3, полу- чить хорошую верхнюю оценку на количество разворачиваемых ребер — (|£|/4). Дальнейшие поиски сложных нелинейных эвристик стоит считать малоперспектив- ными, поскольку, во-первых, вряд ли есть эвристика с хорошим наихудшим случаем, а, во-вторых, незначительное добавочное уменьшение количества развернутых ребер не оказывает существенного влияния на качество получаемого изображения. Известно формулировка данной задачи в терминах линейного целочисленного про- граммирования. Использование метода ветвей и границ позволяет получить точное решение искомой задачи. Данный метод может быть применен для практического изучения результатов работы других алгоритмов. 5.4. Иерархические графы и графовые модели Широкая применимость графов связана с тем, что они являются весьма естественным средством объяснения сложных ситуаций на интуитивном уровне. Эти преимущества представления сложных структур и процессов графами становятся еще более ощути- мыми при наличии хороших средств их визуализации. Поэтому неслучайно в на-
Глава 5. Визуализация 399 стоящее время в мире растет интерес к методам и системам визуальной обработки графов и графовых моделей. Многие программные системы, особенно те, которые используют информационные модели, включают элементы визуальной обработки графовых объектов. Среди них — системы и окружения программирования, инструменты CASE-технологии, системы автоматизации проектирования и многие другие. Понятно, что визуальная обработка графов не сводится к проблемам их визуализации, а включает также широкий круг вопросов, связанных с поддержкой различных процессов анализа и синтеза графовых моделей с использованием человеко-машинного интерфейса, основанного на их на- глядных представлениях. Поскольку информация, которую желательно визуализировать, постоянно увеличи- вается и усложняется, возникает все больше ситуаций, в которых классические гра- фовые модели перестают быть адекватными. Требуются более мощные графовые формализмы для представления информационных моделей, обладающих иерархиче- ской структурой. Иерархичность является основой многочисленных методов анализа и синтеза сложных инфюрмационных моделей в различных областях применения ЭВМ. Необходимость разработки методов и средств поддержки визуальной обработки иерархических графовых моделей вызвана их широким применением в различных областях человеческой деятельности, особенно в связи с активным и повсеместным использованием информационных моделей и технологий. 5.4.1. Иерархические графы Пусть G обозначает граф произвольного вида, элементы (вершины и ребра) которого отличаются один от другого какими-либо пометками, называемыми их именами, на- пример: G может быть орграфом (ориентированным графом), мультиграфом (с крат- ными ребрами) или псевдографом (с петлями). Граф С образован называется фрагментом графа G, обозначаем Сс G, если С — часть графа G, т. е. подмножеством элементов графа G. F— иерархия фрагментов графа G, если F— такое множество фрагментов графа С, чтоб e F и для любых двух фрагментов Ci и С2 из F либо фрагменты С| и С2 не пе- ресекаются. либо один из них является частью (подфрагментом) другого. Фрагмент G— основной (главный) фрагмент иерархии F. Фрагмент С е F — элементарный, если в F нет фрагментов G, являющихся подфрагментами фрагмента С. Пусть задана некоторая иерархия фрагментов F графа G. Для любых Сь С2 е F фрагмент С] — прямой подфрагмент С2 (или, что то же самое, фрагмент, непосредст- венно вложенный в С2), если Ci — подфрагмент С2 и не существует такого С3 е F, отличного от Ct и С2, что С, с С3 с; С2. Иерархический граф H=(G, Т) состоит из графа G и корневого дерева Т, вершины которого соответствуют элементам некоторой иерархии в G, а дуги отражают отно- шение их непосредственной вложенности. Т называется деревом вложенности, а G— основным графом иерархического графа Н
400 Часть I. Обработка и визуализация графов Пример иерархического графа Н= (G, Т) приведен на рис. 5.42. Здесь и в дальнейшем рядом с вершинами дерева Т указаны имена фрагментов, которым они соответст- вуют. Рис. 5.42. Пример связного иерархического графа Рис. 5.43. Пример несвязного иерархического графа Граф Н называется иерархическим графом с тривиальной иерархией, если дерево Т— тривиальный граф, т. е. состоит из единственной вершины G. Указанный класс иерархических графов представляет обычное понятие графа. Для любой вершины р дерева Т через Т(р) обозначается максимальное поддерево де- рева Т с корнем р, а через G(p) — фрагмент основного графа G, соответствующий р. Иерархический граф Н(р) = (G(p), Т{р)) называется иерархическим подграфом графа Н, ассоциированным с вершиной р. Граф H=(G, Т) называется связным, если для любой вершины р дерева Т фрагмент G(p) основного графа G, соответствующий р, является связным. Иерархический граф Н = (G, Т) на рис. 5.42 является связным. На рис. 5.43 демонст- рируется пример несвязного иерархического графа, основной граф которого является связным.
Глава 5. Визуализация 401 Пусть //t=(G|, Т\) и Н2 = (G2, Т2)— два иерархических графа. Н\ называется под- графом Н2, если Т\ — поддерево дерева Т2 и для любой вершины р из Т} граф б|(д) — часть графа G2(p). Важный частный случай иерархических графов образуют такие H=(G, Т), что каж- дая вершина дерева вложенности Т соответствует некоторому подграфу основного графа G. Такие графы будем называть простыми иерархическими графами. Посколь- ку подграфы однозначно определяются множествами своих вершин, есть возмож- ность определять простой иерархический граф И как пару (G, Т), состоящую из ос- новного графа G и вершинного дерева вложенности Т, удовлетворяющего следую- щим условиям. Вершины дерева Т соответствуют некоторым подмножествам вершин основного графа G таким образом, что подмножества вершин, соответствующие ли- стьям Т, образуют разбиение множества всех вершин графа G на одноэлементные подмножества. Дуги дерева Т отражают непосредственную вложенность соответст- вующих подмножеств. Такое представление иерархического графа будем называть вершинным. Рис. 5.44. Пример простого иерархического графа Н = (G, Г): a — основной граф G, б — единственный нетривиальный фрагмент, отличный от G, в — неструктурное изображение D графа Н,Т На рис. 5.44 приведен пример вершинного представления простого иерархического графа H = (G, Т). Здесь и в дальнейшем при изображении дерева Т рядом с листьями указаны вершины одноэлементных множеств, которым соответствуют листья. Заме- тим, что в соответствии с рассмотренным определением простой иерархический граф можно представлять в виде связного графа, отождествляя вершины основного графа
402 Часть I. Обработка и визуализация графов с соответствующими листьями дерева вложенности. Пример такого представления для графа Н (см. рис. 5.44) приведен на рис. 5.45, где ребра основного графа изобра- жены сплошными, а ребра дерева вложенности — штриховыми линиями. Рис. 5.45. Представление простого иерархического графа Н в виде связного графа: ребра основного графа (сплошные линии), ребра вершинного дерева вложенности (штриховые линии) В классе простых иерархических графов естественно выделяется подкласс иерархи- ческих деревьев (G, Т), в которых основной граф G не содержит ребер. Указанный класс иерархических графов представляет понятие корневого дерева. Другой важный подкласс простых иерархических графов — так называемые иерар- хические упорядоченные деревья (G, Г), в которых G является линейным орграфом. Линейное упорядочение вершин основного орграфа G, отражающее достижимость одной вершины орграфа G из другой, индуцирует естественное линейное упорядоче- ние на множестве сыновей любой вершины дерева Т. Таким образом, иерархическое упорядоченное дерево представляет понятие упорядоченного корневого дерева. В терминах иерархических графов зонно-интервальное и гамачное представления уграфа, рассмотренное ранее, можно переформулировать следующим образом. Рассмотрим в качестве F минимальное множество фрагментов уграфа G, содержащее G и замкнутое относительно следующего правила: если С е F и р является такой на- чальной вершиной фрагмента С, что фрагмент {/?} не принадлежит множеству F, то в F включаются все бикомпоненты графа, полученного из С удалением всех дуг, захо- дящих в р. Пусть И/. = (G, 7) — простой иерархический граф, в котором Т—- дерево вложенности, соответствующее построенному F. А. Граф G является регуляризуемым тогда и только тогда, когда для некоторого простого иерархического графа Hp=(G, Г) множество {G(p) : р— вершина дере- ва Т, соответствующая нетривиальному собственному фрагменту графа G} — иерархия вложенных одновходовых зон графа G.
Глава 5. Визуализация 403 Б. Грек}) G является регуляризуемым тогда и только тогда, когда существует та- кой простой иерархический граф Hr.- = (G, Т), что для любой вершины р е G интер- валом является соответствующий вершине р фрагмент графа, полученного из G стягиванием в вершины всех фрагментов, соответствующих сыновьям р в Т. В отличие от зонно-интервального представления Н,. - (G,T), которое возможно только для сводимых уграфов и объединяет выделение иерархии как интервалов, так изон, любой уграф программы представим в виде иерархии альтов, являющихся про- стыми и составными гамаками. Такое представление не требует изменения алгоритма обработки программ при его факторизации, а также выделяет фрагменты, способные к перемещению в программе. Рассмотрим в качестве С множество всех простых и составных гамаков уграфа G. Пусть Нс = (G, Т) — простой иерархический граф, в котором Т — дерево вложенно- сти, соответствующее рассмотренному С В.Дтя любого графа G его представление в виде простого иерархического графа H(=(G, Т) существует и единственно. 5.4.2. Изображения иерархических графов Пусть задан некоторый иерархический граф Н = (G, Т), у которого G не является ги- перграфом. Изображением иерархического графа Н называется представление его элементов (вершин, фрагментов и ребер) на плоскости в соответствии со следующими тремя правилами. 1. Каждая вершина графа G представляется точкой или некоторой простой замкну- той областью R, определяемой простой (не имеющей самопересечений) замкнутой кривой — ее границей. Изображения разных вершин не пересекаются 2. Каждый фрагмент С, являющийся вершиной дерева Т, представляется простой замкнутой областью таким образом, что представления всех вершин и фрагментов графа Н, содержащихся в С, целиком расположены строго внутри области, пред- ставляющей С (т. е. они принадлежат этой области и не содержат точек ее грани- цы), а представления всех вершин и границ фрагментов графа Н, не содержащихся в С, целиком расположены вне области, представляющей С (т. е. они не имеют с ней общих точек). 3. Каждое ребро графа G представляется простой кривой, соединяющей по одной точке из представлений соответствующих вершин графа G, которым она инци- дентна, и пересекающейся с этими представлениями в точности по этим двум точ- кам (эти точки являются концами кривой, представляющей ребро). Дуга графа G представляется аналогично за исключением указания направления на кривой. Кривые, представляющие разные ребра и дуги, пересекаются между собой и с границами фрагментов лишь в конечном числе точек и не имеют общих точек с изображениями вершин, которым они не инцидентны. Будем называть изображение D графа Н структурным, если представление любого ребра (и дуги), соединяющего некоторые вершины р и q в Н, пересекает границу не- *
404 Часть I. Обработка и визуализация графов которого фрагмента С только тогда, когда ребро не принадлежит фрагменту С, при- чем само пересечение не содержит больше чем |{р, q} А С| точек, и неструктур- ным — в противном случае. Наряду с полным изображением иерархического графа можно рассматривать и час- тичные его изображения, в которых некоторые элементы графа не имеют изображе- ний. Например, во многих приложениях нет необходимости изображать главный фрагмент. Другой пример частичных изображений— это изображения иерархического графа, определяемые разными сечениями его дерева вложенности Т. Сечением дерева Т на- зывается такое множество М его вершин, что справедливы следующие два свойства: никакие две вершины из М не лежат на одном пути в Т, и ни одну вершину дерева Т нельзя добавить к Л/, не нарушив первого свойства. В частичном изображении графа, определенном некоторым сечением М дерева Г, для любой вершины р е Л/, соответствующей некоторому фрагменту С, иерархический подграф Н(р) представлен лишь изображением его главного фрагмента С. Другими словами, в таком изображении иерархического графа все представления фрагментов, соответствующих элементам множества Л7, являются как бы "непрозрачными", скры- вающими представления всех элементов графа, содержащихся в них. Понятно, что при переходе от полного изображения основного графа к некоторому его частичному изображению могут возникать кратные ребра, даже если основной граф не является мультиграфом. Их можно изображать независимо друг от друга ли- бо одним ребром. Выбор в пользу того или иного представления указанных ребер зависит от класса решаемых задач. Отметим, что рассмотренное понятие изображения иерархического графа формали- зует понятие его укладки на плоскости и позволяет обобщить на класс иерархических графов и другие понятия теории графов, обычно используемые при исследовании топологических характеристик графов Заметим также, что здесь и в дальнейшем мы используем термины "ребро" и "дуга" по отношению к иерархическому графу Н и его изображению D для обозначения тех кривых, которые представляют соответствующие ребра и дуги графа Н в его изобра- жении D. Аналогично, термины "вершина", "фрагмент", "граница вершины" и "гра- ница фрагмента" будут использоваться по отношению к иерархическому графу Н и его изображению D для обозначения областей и границ областей, представляющих в D соответствующие элементы графа Н. Пересечение двух ребер щ и и2 изображения D иерархического графа Н— это мно- жество общих их точек, не принадлежащих вершинам, которым они инцидентны. Если это множество состоит из п точек, то будем говорить, что ребра имеют п пере- сечений, когда п > 0, и не пересекаются, когда п = 0. Изображение D графа И называется плоским, если в нем нет пересекающихся ребер или дуг. Граф Н называется планарным, если он имеет плоское структурное изобра- жение Понятно, что каждое иерархическое дерево аналогично обычному "дереву" является планарным. Вместе с тем понятие планарности иерархического графа не совпадаег с понятием планарности его основного графа.
Глава 5. Визуализация 405 Рассмотрим планарный граф G на рис. 5.46. Он образует простой иерархический граф (G, Т), который явно не является планарным в силу непланарности фактор-графа R(G), где R= {А = {a, cl, g}, B={b,e,h}, С= {c,f,i}}. Таким образом, справедливо следующее свойство. R(G) Рис. 5.46. Непланарный иерархический граф А. Существуют непланарные иерархические графы, основные графы которых явля- ются планарными. На рис. 5.44 приведен планарный граф G и иерархический граф Нс основным графом С и единственным, отличным от G, нетривиальным фрагментом С. Очевидно, что Н не является планарным, но имеет плоское изображение D, не являющееся структур- ным. Таким образом, справедливо следующее свойство. Б. Существуют непланарные иерархические графы, основные графы которых име- ют плоские неструктурные изображения. Пусть //= (G, Г) — простой связный иерархический граф. Понятно, что если он явля- ется планарным, то в силу определения существует такое плоское изображение графа С, что для любой вершины р е'Т все элементы графа G\G(p) находятся на внешней грани изображения графа G(p). С другой стороны, если существует такое плоское изображение графа G, что для любой вершины р е Т все элементы графа G\G(p) на- ходятся на внешней грани изображения графа G(p), то можно построить структурное изображение Н следующим образом: последовательно рассматривать вершины р де- рева вложенности Т по уровням, начиная с листьев и двигаясь вверх к корню, и на каждом шаге изображать границу подграфа Ср, соответствующего вершине р, во внешней грани С(р) вдоль границы ее внешней грани на расстоянии е > 0 от этой границы и границ подграфов, вложенных в G(p). Таким образом, справедлив сле- дующий критерий планарности простого связного иерархического графа. В. Простой связный иерархический граф H= (G,T) является планарным тогда и только тогда, когда существует такое плоское изображение графа G, что для
406 Часть I. Обработка и визуализация графов любой вершины р е Т все элементы графа G\G(p) находятся на внешней грани изо- бражения графа G(p). Вопросы построения изображений иерархических графов на плоскости весьма важны и трудны, как в смысле сложности формализации "хорошего" (наглядного) изобра- жения того или иного класса графов, так и в смысле сложности алгоритмов построе- ния указанных "хороших" изображений. Нужно отметить, что различные приложения накладывают дополнительные ограничения на изображения планарных графов и да- же деревьев. При этом большинство графов, возникающих на практике, не планарны, т. е. не могут быть изображены на плоскости без пересечений ребер. Поэтому возни кает задача нахождения такого изображения непланарного графа, ребра которого имеют пересечения, но изображение обладает как можно большей наглядностью, например, имеет наименьшее число пересечений ребер. Другие, обычно используе- мые при оценке качества изображения характеристики графа, такие как род, число скрещиваний, толщина или искаженность, также естественным образом обобщаются на класс иерархических графов в соответствии с введенным в данном разделе поня- тием укладки иерархического графа на плоскости. Рис. 5.47. Пример изображения гиперграфа В случае, когда основной граф иерархического графа— гиперграф, возникает во- прос, как изображать ребра, являющиеся не обязательно двухэлементными подмно- жествами его вершин. Один из возможных подходов — использование для их изо- бражения гиперкривых, определяемых по следующим двум правилам: □ любой отрезок простой кривой — гиперкривая, граничные точки которой — гра- ничные точки отрезка, а основа — все точки отрезка, отличные от его границ; □ если аир — две гиперкривые, пересечение которых состоит из одной точки р граничной у а и принадлежащей основе р, то кривая, полученная объединением а
Глава 5. Визуализация 407 и Р, является гиперкривой, основа которой — это основа а, а множество гранич- ных— объединение всех граничных точек р и тех граничных точек а, которые отличны отр Гиперкривая соединяет свои граничные вершины и может использоваться в опреде- лении изображения ребра графа вместо простой кривой. Дуга гиперграфа может изо- бражаться аналогично, за исключением указания направлений от одних граничных вершин к другим (рис. 5.47, где вершины и фрагменты гиперграфа G изображены в виде прямоугольников). 5.4.3. Иерархические графовые модели Под графовой моделью в общем случае будем понимать класс графовых объектов, имеющих вид помеченных графов, с заданным на нем отношением эквивалентности. При этом при задании графовой модели будем различать статическую (или синтакси- ческую) часть описания, определяющую класс помеченных графов, образующих ука- занную модель, и динамическую (или семантическую) часть, задающую разбиение данного класса графов на подклассы попарно эквивалентных. Термин "графовая мо- дель" будет использоваться для обозначения как всего класса объектов, составляю- щих ее, так и для отдельных элементов этого класса. Пусть имеется множество объектов V, называемых метками, распадающееся на по- парно непересекающиеся подмножества классов меток. В качестве классов меток могут использоваться определенные множества чисел, символов, строк (цепочек символов), формул, графов и объектов других видов. Пусть задано множество объектов W, называемых типами, и пусть каждому элемен- ту w е W поставлено в соответствие множество пометок Г'(м), имеющее вид декар- тового произведения где (/J- е V — некоторый класс меток для любого ). Со статической точки зрения иерархическая графовая модель — это тройка (Н, М, L), где//—иерархический граф, М— функция типа, приписывающая каждому элемен- ту (вершине, ребру и фрагменту) h иерархического графа Н его тип M(h) е W, a L — функция меток, приписывающая каждому элементу h графа Н его пометку — неко- торый элемент /,(/?) е И(Л7(/?)). При изображении графовой модели тип ее элементов может быть связан с опреде- ленной геометрической формой соответствующих представлений и/или их цветовой гаммой, а также местом и способом представления пометок, относящихся к элемен- там соответствующего типа. Что касается динамической части иерархической графовой модели, то она может быть задана разными способами и привносить в визуализацию графовых моделей различные анимационные аспекты. Можно выделить два разных подхода к заданию семантической части графовой мо- дели: путем явного задания набора инвариантов (свойств, характерных всем эквива- лентным между собой моделям), который различает классы эквивалентности графо- вых моделей, либо через так называемые эквивалентные преобразования графовых
408 Часть I. Обработка и визуализация графов моделей, которые сохраняют указанный набор инвариантов. Оба подхода к заданию семантической части графовой модели опираются на преобразования графов и ак- тивно развиваются в рамках теории схем программ, где первый подход приводит к семантическим моделям программ, используемым, главным образом, для исследова- ния проблем разрешимости и обоснования корректности преобразований, а второй — к формальным моделям программ, ориентированным на исследование различных формализаций применяемых на практике способов улучшения качества транслируе- мых программ, так называемых оптимизирующих преобразований. Важным при изображении иерархической графовой модели является наглядное пред- ставление свойств, возникающих из-за двойственной роли фрагмента (их мы будем называть свойствами часть-целое'). Каждый фрагмент С иерархической графовой модели, с одной стороны, определяет, как правило, некоторую ее подмодель — ту, главным фрагментом которой он является, а с другой — выступает в роли вершины (в фактор-модели, получаемой из исходной стягиванием С в вершину). В частности, в уграфе G фрагмент С может рассматриваться как уграф, начальная вершина которого— это начальная вершина С в G, а множество конечных— это множество выходных вершин С в G, а также как отдельный оператор в соответст- вующем уграфе. Поэтому фрагменты уграфа должны помечаться символами опера- торов, причем желательно, чтобы эквивалентно работающие в G фрагменты помеча- лись одинаковыми символами операторов. 5.4.4. Использование инвариантных свойств для задания семантики модели Первый подход к заданию семантической части графовой модели характеризуется рассмотрением некоторых порождающих процессов, тем или иным способом описы- вающих функционирование модели и позволяющих (не всегда конструктивно) свя- зать с моделью набор инвариантов (инвариантных свойств), различающих классы эквивалентности. Например, при представлении в виде графовой модели некоторого класса программ, реализующих некоторые функции (а это, как правило, так), имеет место естественное и наиболее общее (слабое) определение эквивалентности, требующей лишь равенства функций, вычисляемых программами, — так называемая функциональная эквива- лентность. Однако в силу известных результатов об алгоритмической неразрешимо- сти распознавания любого внутреннего (инвариантного относительно функциональ- ной эквивалентности) свойства программ в любом достаточно содержательном (на- пример, вычисляющем все рекурсивные функции) классе программ рассматриваются более сильные отношения эквивалентности. Основным методом сужения понятия эквивалентности является сравнение не функ- ций, реализуемых программами, а некоторого вида историй их вычисления в процес- се выполнения программ. Вид истории может быть произвольной степени детально- сти, лишь бы по ней однозначно восстанавливался результат выполнения программы. Тем самым программы с совпадающими историями автоматически имеют совпа- дающие результаты, т. е. являются функционально эквивалентными Поэтому в гра-
Гпава 5. Визуализация 409 фовой модели, представляющей класс программ, обычно используется некоторый вид таких историй. Для программ, при представлении которых в виде графовой модели соответствую- щие операторам вершины графа разделяются на преобразователи, имеющие не более одной исходящей дуги, и распознаватели, имеющие более одного преемника по управлению, но не изменяющие состояние памяти (т. е. не имеющие результатов), обычно рассматриваются следующие основные виды историй. Операционная история программы — запись последовательности преобразователей, выполняемых при работе программы. Операционно-логическая история программы дополнительно указывает на все распо- знаватели, пройденные при работе программы. Информационный граф реализации программы. Вершинами графа являются преобра- зователи. Вершина S) соединяется с вершиной S2, если S2 использует результат S) в качестве аргумента. Информационно-логический граф реализации программы. К информационному графу добавляются вершины проходимых распознавателей. Их аргументы соединяются с соответствующими результатами информационными связями. Кроме того, каждый распознаватель соединяется связью особого рода с каждой вершиной информацион- но-логического графа, прохождение или непрохождение которой непосредственно зависит от выполнения данного распознавателя. Термальное значение результирующих переменных. Очевидно, что информационный граф является ациклическим. Это позволяет для каждого аргумента х любой верши- ны 5 графа построить некоторое дерево, которое называется термальным значением аргумента а и включает в себя все вершины, достижимые из S при движении на- встречу дугам информационнных связей. Если некоторая вершина при этом движе- нии достижима по нескольким путям, она в дереве расклеивается на соответствую- щее количество экземпляров. Продвигаясь "вниз" по информационному графу и строя термальные значения аргументов, можно получить в конце концов термальные значения результативных переменных. Логико-терма/ьная история реализации получается добавлением к терминальному значению результативных переменных цепочки пройденных распознавателей вместе с терминальными значениями их аргументов. Логико-термальная история строится по информационно-логическому графу. Аналогичный подход используется и в теории схем программ. В схеме программ со- храняется значительная часть структурных свойств программ, в частности, членение на операторы с указанием информационных и управляющих связей между ними. Каж- дая схема описывает не одну, а целый класс программ, имеющих одну и ту же струк- туру. Конкретные программы получаются из схемы допустимыми интерпретациями формальных символов, входящих в схему вместо переменных, операций и других объектов, образующих конкретные программы, которые моделируются этой схемой. Теория схем строится так, чтобы факт, установленный для некоторой схемы, был бы справедлив для любой интерпретирующей ее программы. В частности, две схемы программ а! и а2 объявляются эквивалентными в смысле некоторой истории Н, если
410 Часть I. Обработка и визуализация графов для любой допустимой интерпретации будут эквивалентными в смысле этой истории конкретные программы тс, и л2, получаемые из ct| и а2 данной интерпретацией. Необходимо отметить, что преобразования графов, используемые в рамках этого подхода, при их визуализации требуют поддержки управляемой анимации указанных порождающих процессов, позволяющей пользователю прокручивать их в прямом и обратном направлении, начиная с любого момента, и взаимодействовать с ними че- рез элементы визуализации, в частности, останавливать процесс в любой точке и/или при достижении определенных условий, изменять способ визуализации процесса и его параметры. Определенные сложности визуализации порождающих процессов возникают для графовых моделей "неалгоритмических" параллельных систем с недетерминирован- ным поведением, в которых отдельные компоненты функционируют в основном не- зависимо, взаимодействуя друг с другом время от времени. Примером таких моделей являются сети Петри и их различные модификации. Иерархические сети Петри — это обобщенная сеть, в которой наряду с обычными (простыми) переходами допускаются и составные переходы, имеющие внутреннюю структуру и являющиеся, по существу, самостоятельными (иерархическими) сетями. Такой вид сетей служит для моделирования иерархических систем, которые, наряду с неделимыми атомарными компонентами, содержат составные компоненты, сами представляющие собой системы (быть может, также иерархические). Следует заметить, что вопросы визуальной обработки недетерминизма возникают и в графовых моделях последовательно функционирующих систем. Например, в теории схем программ вместо универсального алгоритма выполнения схемы и следящего алгоритма, порождающего истории ее выполнения того или иного вида, рассматри- ваются также "покрывающие" их порождающие процессы, которые определяют множество абстрактных реализаций схемы, включающее в себя множество реализа- ций любой интерпретации данной схемы. Как правило, этим процессам характерен недетерминизм: на каждом шаге применения процесса производится свободный вы- бор одной из нескольких альтернатив без учета предыдущей истории процесса. Это позволяет привести множество порождаемых схемой реализаций к виду, допускаю- щему эффективное решение массовых проблем, связанных с этим множеством (на- пример, прийти к эквивалентности, проблема распознавания которой алгоритмически разрешима). 5.4.5. Трансформационный подход к заданию семантики графовой модели Второй подход к заданию семантической части графовой модели — это задание сис- темы преобразований графовых моделей, сохраняющих эквивалентность (так назы- ваемых эквивалентных преобразований). При этом желательно иметь систему преоб- разований, полную в том смысле, что любая пара эквивалентных моделей может быть сведена одна к другой с помощью этой системы. Однако далеко не всегда конечные полные системы преобразований существуют, поэтому рассматриваются и такие сис- темы эквивалентных преобразований, которые не обладают свойством полноты. Как правило, используемые на практике системы эквивалентных преобразований не об-
Глава 5. Визуализация 411 ладают также свойством Черча — Россера, позволяющим не следить за порядком применения преобразований. Исследованием правил преобразования графов занимается теория графовых грамма- тик и систем переписывания графов. Графовая грамматика (или система переписывания графов) состоит из множества правил (графовых продукций), которые могут итеративно применяться к графу, про- изводя (обычно) его локальные преобразования. Иногда выделяются некоторый граф в качестве начального, а также множество терминальных меток (или используется любое другое средство для характеристики некоторого множества графов, рассмат- риваемых в качестве терминальных). Указанное выделение начального и терминаль- ных графов позволяет в большей степени говорить о графовой грамматике (по анало- гии с порождающей грамматикой), а не о системе переписывания графов. Графовая продукция обычно состоит из тройки (£, R, Е), где L и R — два графа, назы- ваемые соответственно левой и правой частями продукции, а Е— некоторый меха- низм встраивания. Продукция р может быть применена к некоторому заданному обрабатываемому гра- фу G в соответствии со следующей последовательностью действий: I. Находится вхождение левой части £ в G (в некоторых случаях дополнительно требуется выполнение определенных условий применимости). 2. Удаляется часть графа G, определенная указанным вхождением £, для получения контекстного (или остаточного) графа D. 3. Встраивается в D правая часть (копия) R с помощью механизма встраивания Е и получается выведенный граф Н. л В этом случае используют обозначение G=>H и говорят, что имеется непосредст- венный вывод Н из G с помощью р. Различные подходы к формализации преобразо- ваний графов отличаются друг от друга: Л видами графов, подвергающихся переписыванию; П возможными ограничениями, которым должна удовлетворять левая часть про- дукции; Л способами, по которым определяется вхождение £ в G, и соответствующими условиями применения; □ механизмами встраивания. При использовании правил преобразований для задания семантической части графо- вой модели возникают вопросы поддержки визуальной обработки системы преобра- зований, связанные с их визуальным конструированием, применением и анализом. Властности, весьма важной является возможность поддержки управляемого визу- ального применения системы преобразований, позволяющего в каждый момент зада- вать, какое преобразование и каким образом нужно применить к текущему виду мо- дели, а также возвращаться к виду модели, бывшему у нее до применения преобразо- вания. I Нужно подчеркнуть важную роль вопросов визуальной обработки систем преобразо- ваний и для случая явного описания семантической части графовой модели Многие
4/2 Часть I. Обработка и визуализация графов из порождающих процессов удобно не рассматривать как неделимое глобальное пре- образование, а задавать с помощью системы локальных преобразований. Именно такая ситуация, например, имеет место для сетей Петри, функционирование которых описывается в терминах локальных преобразований, представляющих срабатывания переходов. Формализмы преобразования графов первоначально возникли и развивались как обобщение грамматик Хомского и систем переписывания термов. Эти исследования привели к существенным результатам в области преобразования графов, которые нашли свое применение во многих областях информатики. В настоящее время преоб- разования графов начинают рассматриваться в качестве парадигмы вычислений для сложноструктурированного программного обеспечения и графического интерфейса. Обычные вычисления реализуются на уровне машин фон Неймана с использованием машинных команд и регистров. Уровень вычисления заметно повышается при пере- ходе к ассемблерам и языкам программирования высокого уровня и далее к функ- циональным и логическим языкам программирования. Вид вычисления более вы- сокого уровня в основном базируется на понятии переписывания термов, которое в терминологии графов и графовых преобразований соответствует понятию преобра- зования деревьев. Деревья, однако, не допускают разделения общих структур, работа с которыми является основой повышения эффективности при реализации логических и функциональных программ. Это приводит к рассмотрению графов, а не деревьев в качестве фундаментальных структур при определении понятия вычисления, в рамках которого унифицированным образом могут быть промоделированы и изучены пре- образования весьма разнообразных структур. 5.5. Системы визуализации графов и графовых моделей Преимущества графовых моделей во многих случаях становятся ощутимыми только при наличии хороших инструментальных средств их визуализации и обработки. По- этому в настоящее время в мире происходит значительный рост интереса к методам и системам визуализации графов, о чем свидетельствует рост публикаций, содержащих описание новых алгоритмов, способов визуализации графов и новых инструменталь- ных средств. При описании основных систем визуализации графов и графовых моделей будут рас- сматриваться следующие аспекты: основное назначение системы, графические воз- можности системы, интерфейс пользователя, встроенные алгоритмы рисования гра- фов, прочие возможности системы, а также дополнительная информация о системе. 5.5.1. Вопросы визуализации и визуальной обработки Графы широко применяются в различных областях точных и естественных наук, т. к. позволяют строить наглядные и удобные для обработки модели сложных структур.
Глава 5. Визуализация 413 При создании таких моделей граф наделяется некоторой семантикой, которая обычно выражается набором атрибутов, приписываемых его вершинам и дугам. Разработка средств визуализации графов началась во второй половине 80-х годов и существенно активизировалась с начала 90-х XX века. Это было связано, с одной стороны, с возросшей потребностью оперировать с большими объемами информации и сложными структурами данных, которые достаточно естественным образом пред- ставляются графами, с другой стороны, с существенным прогрессом в развитии ап- паратных средств, позволившим сделать графический интерфейс и компьютерную графику удобным и эффективным средством общения человека с компьютером. Многие системы, особенно ранние разработки, возникали как части более крупных проектов, в которых требовался компонент, производящий визуализацию. Некоторые из таких систем позже удавалось сделать более универсальными и оформить как са- мостоятельные программные продукты. В других случаях особенности изначальной ориентации системы оказывались столь существенными, что она могла применяться только для узкоспециальных целей. Таких систем в настоящее время создано доста- точно много. Еще большее количество различных программ содержит сравнительно простые компоненты визуализации графов, предназначенные только для вывода не- которой структурированной информации. Примером может служить вывод дерева классов в компиляторе Borland C++. В середине 90-х годов XX века были сделаны попытки создания универсальных сис- визуализации графов. Хотя при создании этих систем опять заранее намечалось, в каких проектах их предполагается использовать, универсальность теперь заклады- валась изначально. Широкое использование универсальных графовых визуализаторов и особенно графо- вых редакторов затруднялось тем, что в каждом проекте требуется работать с графа- ми, имеющими специфическую семантику. В то же время, не существовало систем, которые позволяли бы настраиваться на семантику графа без изменения кода самой системы. Требовалось, во-первых, создать соответствующее внутреннее представле- ние, во-вторых, организовать визуализацию графа так, чтобы полноценно представ- лять все атрибуты его вершин и дуг. Необходимым требованиям удовлетворяли библиотеки классов на C++, позволяю- щие описывать семантику графа путем создания производных классов с дополни- тельными атрибутами. Такие библиотеки обычно включают множество других по- лезных функций, связанных как с визуализацией графов, так и с выполнением на них различных теоретико-графовых алгоритмов и алгоритмов рисования. Зачастую библиотеки для работы с графами возникают как побочный продукт при создании систем визуализации графов. И наоборот, при разработке каждой библио- теки создается хоть бы небольшая система, необходимая для тестирования библиоте- ки и демонстрации ее возможностей. Кроме того, новые системы могут создаваться на основе уже существующих библиотек. В последнее время с развитием науки о визуализации графов и ее повсеместным рас- пространением начали в большом количестве появляться системы, развивающие от- дельные аспекты данного направления, считающиеся перспективными в настоящее время. В качестве примеров можно привести системы, работающие с трехмерными
414 Часть I. Обработка и визуализация графов изображениями графов. Хотя до сих пор не создано полноценного редактора для та- кого представления, трехмерная визуализация графов уже используется на практике. Другим примером является визуализация очень крупных графов, т. е. графов с на- столько большим числом вершин, что применение обычных методов визуализации для них невозможно. Данная проблематика не в последнюю очередь связана с попу- ляризацией Интернета и необходимостью вести исследования различного характера в области больших компьютерных сетей. Стоит отметить, что создание среднего по возможностям графового редактора явля- ется сравнительно легкой и очень полезной задачей для начинающего программиста или человека, решившего освоить методы создания графических программ или, к примеру, изучить новый язык программирования. Этим, по всей видимости, объясня- ется большое число систем, написанных на ставшем популярным во второй половине 90-х годов XX века языке Java. В качестве примеров можно привести VGJ, Grappa и Graph Drawing Server. Иногда такие системы состоят из клиентской и серверной час- ти. Клиентская часть служит графовым редактором, а на сервере запускаются алго- ритмы рисования или преобразования графов. Существующие системы визуализации графов можно условно разделить на два класса. К первому (более широкому) классу относятся узкоспециальные системы, которые ориентированы на графовые модели с определенной семантикой и топологией. Каж- дая такая система является, как правило, частью некоторого большого проекта, включающего ее в качестве визуализатора каких-либо специфических для данного проекта данных. Более широкое использование таких систем либо очень затруднено, либо просто невозможно. Второй класс — это универсальные системы визуальной обработки графовых моде- лей, такие как daVinci, GraphEd, Graphlet, GraVis, VCG, Graph Drawing Server, GLT. Несмотря на значительный прогресс в создании универсальных систем, следует от- метить ряд недостатков подавляющего большинства из них. Прежде всего для рос- сийского пользователя общим недостатком этих систем является их ориентация на работу в ОС UNIX на больших рабочих станциях, которыми в достаточной степени оснащены иностранные университеты, их разрабатывающие. Как правило, универ- сальность существующих систем весьма ограничена, в частности ни одна из них не позволяет графовым моделям быть иерархическими и не поддерживает визуализа- цию алгоритмов их обработки. Требования к универсальным системам визуализации и визуальной обработки ин- формационных моделей сложны для формализации и нуждаются в отдельном иссле- довании. Отметим лишь, что такие системы должны обладать базовыми возможно- стями поддержки визуальной обработки, связанной с решением широкого круга за- дач анализа и синтеза иерархических графовых моделей в их конструкторском, исследовательском и учебном применении. Система должна поддерживать визуализацию и редактирование помеченных иерар- хических графов. В частности, при изображении графовой модели тип ее элементов может быть связан с определенной геометрической формой соответствующих пред- ставлений и/или их цветовой гаммой, а также местом и способом представления по- меток, относящихся к элементам соответствующего типа.
Глава 5. Визуализация 415 Система должна обладать современным графическим интерфейсом, ориентирован- ным на иерархичность графовых моделей и поддерживающим их многооконное ре- дактирование и визуализацию с возможностями регулирования масштаба, использо- вания разных геометрических и цветовых образов для формирования изображения графа, работы с прямоугольной сеткой для выравнивания объектов и т. п Система должна обладать рядом возможностей, облегчающих и автоматизирующих отдельные операции конструирования, визуализации и изучения различных объектов и явлений в рамках их иерархических графовых моделей, включая возможности от- ката (функция Undo), генерации случайных графов, автоматического расположения графов на плоскости, анимации процессов обработки графовых моделей и специали- зации системы. При использовании правил преобразований для задания семантической части графо- вой модели возникают вопросы поддержки визуальной обработки системы преобра- зований, связанные с их визуальным конструированием, применением и анализом. В частности, весьма важной является возможность поддержки управляемого визу- ального применения системы преобразований, позволяющего в каждый момент зада- вать, какое преобразование и каким образом нужно применить к текущему виду мо- дели, а также возвращаться к виду модели, имеющемуся у нее до преобразования. Нужно подчеркнуть важную роль вопросов визуальной обработки систем преобразо- ваний и для случая явного описания семантической части графовой модели. Многие из порождающих процессов удобно не рассматривать как неделимое глобальное пре- образование, а задавать с помощью системы локальных преобразований. Именно такая ситуация, например, имеет место для сетей 11етри, функционирование которых описывается в терминах локальных преобразований, представляющих срабатывания переходов. Важным при изображении иерархической графовой модели является наглядное пред- ставление свойств, возникающих из-за двойственной роли фрагмента (их можно на- зывать свойствами "часть-целое"). Каждый фрагмент С иерархической графовой мо- дели, с одной стороны, определяет, как правило, некоторую ее подмодель — ту, глав- ным фрагментом которой он является, а с другой — выступает в роли вершины (в фактор-модели, получаемой из исходной стягиванием С в вершину). В частности, в уграфе G фрагмент С может рассматриваться как уграф, начальная вершина которого — это начальная вершина С в G, а множество конечных — это множество выходных вершин С в G, а также как отдельный оператор в соответст- вующем уграфе. Поэтому фрагменты уграфа при его иерархическом представлении могут помечаться символами операторов, причем желательно, чтобы эквивалентно работающие в G фрагменты помечались одинаковыми символами операторов. 5.5.2. Системы визуализации и графовые редакторы При описании систем будут рассматриваться следующие аспекты: основное назначе- ние системы, графические возможности, интерфейс пользователя, встроенные алго- ритмы рисования графов, прочие возможности системы, дополнительная инфор- мация.
416 Часть I. Обработка и визуализация графов Система daVinci Система daVinci разрабатывается с конца 1992-го года в отделении информатики Бременского университета (Германия). Авторы системы сообщают, что у них имеют- ся сведения о более чем 2000 установок daVinci по всему миру. Существуют версии системы для нескольких UNIX-платформ, включая рабочие станции и персональные компьютеры. Данная система изначально предназначалась для визуализации и редактирования ориентированных ациклических графов с использованием их поуровневого размеще- ния (см. разд. 5.3). Стандартный алгоритм рисования для этого случая раскладывает вершины по уровням так, что все дуги идут от меньших уровней к большим. Если дуга проходит через несколько уровней, то в нее добавляются сгибы, рассматривае- мые как дополнительные вершины с нулевыми размерами, лежащие в пересекаемых дугой уровнях. После этого при помощи различных эвристик происходит упорядоче- ние вершин и сгибов дуг внутри каждого уровня с тем, чтобы минимизировать число пересечений дуг графа. Первое описание алгоритма такого типа было предложено Сигаямой. Все последующие усовершенствования, в том числе алгоритм данной сис- темы, базируются на этой работе. Позже в систему были внесены элементарные изменения, позволившие ей работать и с графами произвольного вида. Эти изменения состояли в введении для каждой дуги специального параметра, задающего, на каком ее конце рисовать стрелку. Доступны четыре варианта: Parent —> Child, Parent <- Child, Parent — Child и Parent < > Child. Таким образом, во внутреннем представлении, которое используется алгоритмом рисования, граф остается ориентированным и ациклическим, хотя внешне может вы- глядеть иначе (рис. 5.48). Система имеет средние графические возможности. Для дуг предусмотрено пять сти- лей линий (дуги рисуются ломаными линиями) и выбор цвета из 24-х вариантов. Для вершин задается форма: Box, Rhombus, Circle, Ellipse, Text или Icon Вершины формы Text и Icon не имеют каемки, характерной для всех других форм вершин. Для вершин формы Icon дополнительно задается имя файла, из которого считывается изображе- ние вершины. Каемка вершины, рисуемая всегда черным цветом, может быть оди- нарной или двойной. Для внутренности вершины цвет выбирается, опять же, из 24-х вариантов. Каждая вершина может содержать внутри некоторый текст, возможно многострочный. Для изображения этого текста можно выбирать один из четырех доступных шрифтов. Палитра шрифтов дополнена переключателями bold и italic. Размер шрифта устанавливается сразу для всего графа. Дуги графа не имеют ассо- циированного с ними текста. Интерфейс системы достаточно удобен, хотя обладает рядом недостатков. Имеется панель инструментов, на которую, однако, вынесено лишь минимальное количество функций. В документации утверждается, что система daVinci сама по себе не являет- ся графовым редактором. Графовый редактор может подключаться к ней как отдель- ное приложение. Действительно, после запуска системы команды меню Edit недос- тупны. Для подключения редактора нужно выбрать в меню File пункт Connect application, после чего в открывшемся диалоговом окне выбрать файл с графовым редактором. Затем граф можно редактировать с помощью команд меню Edit.
Глава 5. Визуализация 417 Подредактированием графа понимается изменение его топологической структуры, а также параметров вершин и дуг. Корректировку расположения вершин можно произ- водить и при отключенном редакторе. Вершины добавляются в граф с помощью команд меню Insert root и Insert child. Первая добавляет вершину, не имеющую ро- ителя, вторая — вершину, родителем которой становится выделенная вершина гра- фа. Можно также добавить дополнительную дугу, выделив две вершины и выбрав пункт Insert edge. После добавления или удаления вершины или дуги алгоритм ри- мания запускается заново. 1зображение графа, полученное алгоритмом рисования, можно корректировать, пе- ремещая вершины внутри уровня и с уровня на уровень. При этом дополнительные сгибы дуг возникают автоматически. Их тоже можно двигать внутри уровня. После такой корректировки граф можно записать в файл вместе с текущим расположением. Другой вариант записи — запись без информации о расположении. При чтении тако- I файла система автоматически запускает алгоритм рисования. Масштаб изображения графа можно менять от 1 до 100%. При этом текст вершин сражается только при максимальном масштабе. Полезной возможностью является |ткрытие отдельного окна, содержащего обзорный вид графа с прямоугольником, краиичиваюгцим видимую в обычном окне часть графа. Однако этот прямоугольник нельзя, как обычно в таких случаях, перемещать по графу. Вместо этого в обзорном кне можно выделить вершину, после чего данный прямоугольник вместе с изобра- жением в обычном окне переместится так, что выбранная вершина попадет в его 14 Зак. 202
418 Часть I. Обработка и визуализация графов центр. При этом окно будет многократно перемигивать, полностью перерисовывать при каждом сдвиге прямоугольника, который перемещается к цели в несколько ша- гов. Этот процесс в описании системы назван "animation". Алгоритм расположения имеет параметр качества от 1 до 5. Чем выше этот параметр, тем дольше работает алгоритм и тем лучше получается итоговое расположение. Кро- ме этого можно регулировать размеры промежутков между вершинами и устанавли- вать направление развертывания уровней (стандартный вариант— сверху вниз). За- пускать алгоритм можно либо на всем графе, либо только на видимой в данный мо- мент его части. В системе предусмотрено еще две полезные возможности, называемые авторами abstraction и navigation. Abstraction— способ скрытия части информации о графе, которая может быть в определенные моменты излишней. Есть два варианта такого скрытия для произвольной вершины графа. > □ Скрыть все дуги, инцидентные данной вершине. П Скрыть подграф, образованный данной вершиной и всеми ее сыновьями. После выполнения этих операций вершина помечается специальным образом. Если далее запустить алгоритм рисования, то он уже выдаст другое расположение. К со- жалению, после применения обратного преобразования открывшиеся вершины могут появиться в каком угодно месте плоскости. Чтобы привести расположение в порядок, нужно снова запускать алгоритм рисования. Navigation предусматривает ряд возможностей по выделению вершин путем "хожде- ния" по графу. Так, например, можно выделить вершину, а потом перейти к ее роди- телю, правому или левому брату и т. д. Можно также организовать поиск вершины по ее тексту. В заключение можно отметить, что несомненным достоинством системы является наличие подробной документации, оформленной в виде HTML-файлов. При этом возможно получение контекстных справок, для чего из системы автоматически запускается Netscape Navigator (если он присутствует на компьютере). Для поиска в help-файлах по ключевым словам используется’специальный Java-апплет. Система VCG Система VCG (Visualization of Compiler Graphs) была разработана в Саарланлском университете (Германия). Данная система не является редактором графов и предна- значена только для их визуализации. Она принимает графы в виде файлов специаль- ного формата, который помимо самого графа может содержать дополнительную ин- формацию о методе визуализации отдельных его компонент, например координаты некоторых вершин. Формат файла достаточно сложен, поэтому, хотя эти файлы и текстовые, их вряд ли возможно создавать и редактировать вручную. Таким образом система целиком предназначена для визуализации автоматически сгенерированных графов. Система VCG создавалась для операционной системы (ОС) UNIX XI1-платформ, но позже была перенесена на графическую оболочку Microsoft Windows 3.1 с неболь- шими сокращениями. Хотя при этом перенесении использовались новые библиотеки,
Глава 5. Визуализация 419 многие особенности системы перекочевали из UNIX XI1 и для пользователя, исполь- зующего операционную систему Windows, выглядят несколько странно. Система имеет сравнительно хорошие графические возможности. Вершины изобра- жаются прямоугольниками, эллипсами, треугольниками и ромбами, дуги — ломаны- ми линиям и либо сплайнами, аппроксимирующими ломаные (см. рис. 5.49). Рис. 5.49. Различные варианты вершин и дуг в системе VCG Используется несколько вариантов присоединения дуги к вершине Цвет вершин и цуг выбирается из 254-х вариантов. Вершины и дуги могут иметь многострочные текстовые метки. При этом шрифт меток и его размер задается отдельно для каждого элемента графа. К сожалению, система не использует шрифты ОС Windows, поэтому набор доступных шрифтов ограничен теми, которые поставляются вместе с системой в неизвестном формате. Пополнять этот набор невозможно. В описании системы утверждается, что для размещения графа в ней используется 13основных методов и 4 способа сокращения числа пересечений дуг. Само по себе заявление достаточно странное, т. к. сокращение числа пересечений дуг есть одна из задач любого метода рисования графов. Трудно сказать, что имели в виду авторы, сообщая про 13 методов, но, если судить по внешнему виду, представляется более
Часть I. Обработка и визуализация графов 420 естественным утверждать, что в данном случае мы имеем дело с одним алгоритмом имеющим очень большое число параметров. Сам же алгоритм аналогичен алгоритму системы daVinci и тоже базируется на алгоритме поуровневого изображения графа предложенного Сигаямой. Авторы утверждают, что приоритетом при разработке это го алгоритма для них была скорость работы. Действительно, алгоритм работает дос таточно быстро даже на больших графах, производя при этом сравнительно качест венное размещение. Кроме того, в системе предусмотрено переключение алгоритма в ускоренный режим по истечении отведенного на размещение времени. Достаточно широкий набор средств просмотра графа, включающий возможность произвольного масштабирования изображения, наличие обзорного окна и использо- вание техники Fisheye, позволяет увеличивать отдельные фрагменты графа, оставляя весь остальной граф в поле зрения, но с меньшим масштабом (рис. 5.50). Внешне это выглядит как просмотр изображения через очень сильное увеличительное стекло. Система Windows Рис. 5.50. Техника Fisheye, позволяющая просматривать в увеличенном виде отдельные фрагменты графа, оставляя весь остальной граф а поле зрения имеет возможность экспортировать изображение графа BMP UNIX-системами. несколько других графических форматов, VCG в PostScript используемых в основном имеет ряд дополнительных возможностей, аналогичных тому, что в daVinci называется abstraction. и
Глава 5. Визуализация 421 VCG поставляется вместе с программой, демонстрирующей возможности системы, последовательно загружая в систему различные графы и давая комментарии о том, какие возможности каждый граф демонстрирует. GraphEd и Graphlet Система GraphEd разрабатывалась в университете г. Пассау (Германия) с 1988-го по 1994-й год, после чего усилия создателей были перенесены на новый проект, полу- чивший название Graphlet. Так как последний включает и расширяет возможности своего предшественника, мы будем рассматривать только его. Graphlet представляет собой комплект инструментальных средств для создания гра- фовых редакторов и программирования алгоритмов рисования графов. Graphlet бази- руется на библиотеке LEDA и языке Tcl/Tk. Tel является универсальным интерпре- тируемым языком программирования, а Тк есть расширение Tel, дополняющее его графическими возможностями. Существуют интерпретаторы Tcl/Tk для различных UNIX-платформ, а также для MS Windows 95/NT. Graphlet включает следующие компоненты: 3 ядро, содержащее основные структуры данных и интерфейсную часть алго- ритмов; □ интерфейсный уровень, содержащий реализацию некоторого расширения Тс1 для работы с графами, названного LedaScript; О основной компонент: графовый редактор, написанный на LedaScript; П модули, содержащие графовые алгоритмы, в том числе алгоритмы рисования, реализованные на C++ и LEDA или LedaScript. Graphlet использует для хранения графов новый формат файла, названный GML. Этот формат претендует на существенную универсальность. Он является текстовым и позволяет определять дополнительные атрибуты для элементов графа. В настоящее время, помимо Graphlet, существует несколько систем, которые позволяют читать и I записывать графы в формате GML. Графовый редактор Graphlet можно охарактеризовать как систему с достаточно спе- цифическим набором возможностей, которые удается изучить только после упорной I борьбы с не очень удобным интерфейсом системы и постоянными сообщениями о I внутренних ошибках, возникающих во время работы. I По сути дела, кроме тех средств, которые могут реально понадобиться при создании I визуального представления графа, в систему включено множество других возможно- I стей, полезность которых сомнительна. Примером таких "странных" возможностей I могут служить вершины в форме дуги окружности (причем всегда верхней правой I четверти) или задание сдвига для точки входа дуги в вершину. Если этот сдвиг не I нулевой, то дуга может кончаться не доходя до вершины, либо, наоборот, заходя I нанес. I Реальных графических возможностей не так много (рис. 5.51). Из обычных форм I вершин используется только прямоугольник и эллипс. Цвет задается произвольным I образом для внутренности вершины и ее каемки. Ширина каемки регулируется. Дуги I рисуются ломаными линиями, для которых также задается цвет и ширина. Вершины I «дуги могут иметь по одной текстовой метке. Хотя формат GML и, как утверждается
422 Часть I. Обработка и визуализация авторами, внутреннее представление системы может ство атрибутов элементов графа, в системе такая хранить произвольное возможность Шрифт и его размер можно выбирать для каждого элемента графа отдельно. колпче не реализована Рис. 5.51. Система Graphlet Как уже было отмечено, интерфейс системы оставляет желать лучшего. Система ра ботает в пяти режимах, переключаемых с помощью панели управления. Первый ре жим служит для создания вершин и дуг. Второй — для выделения групп вершин i дуг. После выделения группы элементов графа можно устанавливать любые пара метры (метки, размеры и т. д.) одновременно для всех выделенных объектов. Крош того, можно перемещать всю группу с помощью мыши и пользоваться операциями Cut, Copy, Paste. Третий режим служит для редактирования меток. Фактически отличается от второго только тем, что запрещается выделять более одного объекта Четвертый режим — для просмотра графа. Все функции редактирования,в нем от- ключены. Наконец, пятый режим реализует стандартную zoom-функцию (выделение на экране прямоугольника и увеличение его содержимого). Для редактирования всех параметров элементов графа используется один блок диа- лога с несколькими кнопками, переключающими его содержимое. Стоит отметить, что размеры вершины графа в системе можно изменить только введя их в численном виде в соответствующие поля этого блока диалога. Система имеет возможность ав- томатически корректировать размеры вершин, исходя из размера содержащегося в них текста, но в этом случае, если вершина имеет форму эллипса, то после такой коррекции текст обязательно будет выступать за ее границу.
Глава 5. Визуализация 423 Достоинством системы является большое количество интегрированных в нее алго- ритмов рисования графов, а также некоторых теоретико-графовых алгоритмов. Всего в системе доступно 14 алгоритмов рисования (5 для планарных графов, 2 для деревь- ев, 1 для ациклических графов и 6 для графов произвольного вида). Graphlet работает на нескольких UNIX-платформах, а также под Microsoft Win- dows 95/NT. Такая переносимость достигается в основном за счет переносимости Tcl/Tk. Хотя, существует интерпретатор этого языка для Microsoft Windows, сам язык изначально разрабатывался для UNIX-платформ, поэтому все интерфейсные особен- ности взяты из системы XWindow. Следствие— медленная работа и неудобство для пользователя, привыкшего к другим стандартам. В заключение необходимо отметить оригинальный подход авторов данного продукта к написанию документации (внушительных размеров манускрипт, посвященный языку GraphScript, описание C++ интерфейса для расширения этого языка и описание формата GML). Графовый редактор, который, как заявлено в [11], является основным компонентом Graphlet, не только не имеет встроенной help-поддержки, но и вообще никак не документирован. Система GraVis Система GraVis разрабатывается в группе параллельного программирования Тубин- генского университета (Германия). Данная система является графовым редактором, оснащенным дополнительной возможностью запуска внешних модулей обработки графа, что используется в основном для встраивания в систему алгоритмов рисо- вания. Графические возможности средние. Используются четыре графических примитива для форм вершин: эллипс, прямоугольник, треугольник и ромб В вершину можно вставлять изображения, которые растягиваются и сжимаются при изменении разме- ров вершины. Вершина с изображением внутри автоматически становится прямо- угольной, но ее каемка не рисуется. Прочие вершины имеют тонкую черную каемку нее цвет изменить нельзя. Можно выбирать цвет внутренности вершины и цвет дуг. Существует 16 доступных цветов (в документации описывается полная палитра), для дуг выбирается стиль ли- нии из 9-ти вариантов. Никакие другие параметры изображения регулировать невоз- можно. В частности, стрелки дуг рисуются самым примитивным образом, а метки вершин и дуг одним и тем же шрифтом черным цветом. Дуги рисуются ломаными линиями. По умолчанию метки вершин размещаются в их центрах, а метки дуг на самом длин- ном звене. Однако эти метки при желании можно переместить практически в любое места. Подобным образом дело обстоит с точкой привязки дуг к вершинам. По умол- чанию дуги ориентируются по центру вершин, но можно перенести точку привязки куда угодно за пределы вершины. Таким образом, изображение графа в системе в принципе может не иметь ничего общего с его топологической структурой. В системе есть один основной режим редактирования и один дополнительный, в ко- тором можно выделять группы вершин и сгибов дуг, после чего двигать их куда-либо
424 Часть I. Обработка и визуализация графов или менять размеры. Такое построение интерфейса авторы считают новаторством особенно отмечают, что в их системе операция, производимая щелчком кнопки мы ши, зависит от того, где этот щелчок был произведен. Сгибы дуг являются неким подобием дополнительных вершин. Скорее всего в реали зации это так и есть. Однако не очень понятно, как далеко эта аналогия распростра няется и до каких пор она совпадает с желаниями авторов. В частности, сгибы дуг могут иметь собственные метки, но при запуске любого алгоритма рисования все сгибы уничтожаются и потом, если нужно, добавляются заново. Для изменения раз мера вершин с помощью мыши около выделенной вершины появляется специальное поле, к которому нужно подвести курсор и нажать левую кнопку, после чего менять размеры двигая мышь. Если выделить группу вершин, то таким образом можно ме нять размеры всех вершин группы. Сгибы дуг также можно выделять, чтобы пере мещать их, но менять их размеры нельзя (соответствующее поле отсутствует). Если же выделить группу, состоящую из вершин и сгибов дуг, а потом воспользоваться полем какой-либо вершины для изменения размеров, то размеры точек сгиба (т. е отмечающих их окружностей) также будут изменяться. Существует возможность использовать сетку для размещения вершин, однако, эта возможность организована крайне неудобно. Сетка всегда квадратная, причем с фик сированным размером. При перемещении вершин она относительная, при изменении их размеров — абсолютная (хотя разумно было сделать и наоборот). При этом разме- ры вершин меняются сразу на два деления сетки. Если учесть, что эти деления столь крупны, что на экране по горизонтали их умещается порядка десяти, то можно еде лать вывод, что от такой сетки трудно ожидать большой пользы. В системе можно отметить три несомненно положительных момента. Во-первых, наличие операций Undo и Redo, позволяющих отменить или повторить действия, во- вторых, возможность выделять мышью некоторую область окна, а затем просматри- вать ее с увеличенным масштабом, в-третьих, возможность запуска внешних моду- лей. Внешний модуль получает на вход текущий граф, обрабатывает его и либо воз- вращает результат системе, либо сам выводит его на экран, если это просто текст. При запуске модуля может возникать блок диалога для ввода дополнительных пара- метров алгоритма. В систему встроено порядка 15-ти модулей, около 10-ти из кото- рых содержат алгоритмы рисования графов. Есть модуль для генерации случайных графов. Интересной особенностью системы является возможность создания иерархических графов. Однако эта возможность организована крайне неэффективно. Можно выде- лить группу вершин и заменить ее одной метавершиной. Если мы теперь захотим посмотреть на свернутые вершины, то для этого потребуется открыть новое окно. Увидеть данные вершины в том же окне что и раньше можно только заменив обратно метавершину на выделенный подграф. Графы можно сохранять либо в собственном формате системы, либо в формате GML. Помимо ряда недоделок и ошибок к недостаткам системы можно отнести крайне медленное функционирование. Для оценки этого качества можно сказать, что, на- пример, при добавлении в граф вершины между щелчком мыши и появлением новой вершины на экране проходит больше секунды (эксперимент проведен на компьютере
Глава 5. Визуализация 425 486DX lOOMhz, 32mb). Кроме того, данная система является лидером среди своих аналогов по количеству "преувеличений достоинств", содержащихся на Web- странице системы и в статьях по системе. Не так давно на базе GraVis был начат новый проект, получивший название YProject. Новая система представляет переработанный и несколько улучшенный вариант гра- фового редактора с аналогичными возможностями. Система написана на языке Java и включает в себя несколько дополнительных функций, таких как анимация алгорит- мов. Эта возможность предусмотрена только для встроенных в систему алгоритмов и пока не сильно развита. Следует отметить, что новая система работает стабильнее ине имеет такого количества недостатков, как GraVis. На рис. 5.52 представлен при- мер создания графа в системе YProject. Рис. 5.52. Окно системы YProject Система VGJ Система VGJ разрабатывается в Аубурнском университете (США). Данная система представляет собой типичный пример написания графового редактора на языке Java. Систему можно оценить как достаточно примитивный графовый редактор с плохо [продуманным пользовательским интерфейсом и слабыми усилиями по получению качественного графического изображения графа.
426 Часть I. Обработка и визуализация графов В данный момент проект находится в недоработанном состоянии (не работают мно- гие необходимые интерфейсные функции, например перемещение сгибов дуг с по- мощью мыши). Для хранения графов используется формат GML, однако реальная совместимость с системой Graphlet, для которой этот формат является базовым, остается под вопро- сом. После перенесения записанного графа в Graphlet топологическая структура гра- фа не изменяется, но изображение существенно искажается. С другой стороны, нель- зя сказать определенно, какая из двух систем несет большую ответственность за это искажение. Графические возможности VGJ включают только минимальный необходимый набор: одноцветные вершины в форме прямоугольников или эллипсов и дуги четырех цве- тов в виде ломаных линий. Для каждой вершины и дуги предусмотрено по одной текстовой метке. Метка вершины располагается либо под вершиной, либо в ее цен- тре. Шрифт для всех меток один и тот же. Можно отметить две оригинальные возможности системы: П возможность построения трехмерных изображений (Граф даже можно вращать в пространстве, выбирая позицию обзора с помощью мыши. Впрочем, изображение графа всегда остается двумерным, т. е. вершины не меняют форму и размеры при поворотах.); □ возможность "свернуть" группу вершин и заменить одной вершиной особого вида Группы могут быть вложенными, их можно открывать и закрывать, но больше ниче- го с ними делать нельзя. Открытая группа никак не отмечается. В GML эти группы записываются как отдельные ни с чем не соединенные вершины, что выглядит весь- ма странно. Недостатки системы в основном происходят из непродуманности тех или иных мо- ментов. Например, force-метод, реализованный в системе, совершенно не учитывает сгибы дуг и размеры вершин; при выборе пункта меню Edit | Remove all edge bends уничтожаются все сгибы, включая сгибы в петлях Подобных примеров можно при- вести достаточно много. Возможности системы ограничены и с точки зрения топологии объекта. В частности, в системе нельзя создавать мультиграфы. При добавлении второй дуги между двумя вершинами первая уничтожается. Наиболее слабым моментом является интерфейс. Неоправданно большое количество режимов и "неочевидных" операций, в которых используются все три кнопки мыши и клавиши <Shift> и <Ctrl>. К счастью, все операции со средней кнопкой мыши про- дублированы другими вариантами. Система SmartDraw Системы визуализации графовых объектов, как правило, ориентированы на примене- ние в профессиональной среде, т. е. их пользователями являются программисты и математики, изучающие те или иные структуры данных или алгоритмы их обработ- ки. Однако с необходимостью построения изображений графов и похожих на них объектов сталкиваются и обычные пользователи. Многие книги, статьи и другие из-
5. Визуализация 427 аваемые материалы часто содержат иллюстрации в виде диаграмм, по сути дела яв- яющихся графами. Особенно это характерно для научных публикаций. Необходимостью быстро и удобно создавать такого рода иллюстрации обусловлено существование класса систем графовых редакторов, нацеленных на непрофессио- ального пользователя. Типичным представителем этого класса является система SmartDraw. На рис. 5.53 приведено окно системы с примером редактируемой диа- граммы. Рис. 5.53. Система SmartDraw Следует отметить, что для систем из этого класса понятие графа как математического объекта отсутствует. Если в математике графы являются удобным механизмом пред- ставления структур данных, то здесь они возникают как удобный механизм пред- ставления изображения, позволяющий редактировать его более удобным способом, чем в графическом редакторе. С другой стороны, SmartDraw это и есть наполовину графический редактор, наполовину система визуализации графов. ВSmartDraw диаграммы составляются из двух видов объектов — форм и линий. Это (соответствует вершинам и дугам в графе. В то же время, каждая форма сама задается набором линий, из которых состоит ее контур. Формы, как правило, соединяются друг с другом линиями, используя так называемые точки присоединения. На линиях контурах форм задается некоторое число таких точек. Если необходимо соединить вершину и форму, то следует совместить какую-либо точку соединения на линии с какой-либо точкой соединения на нужной форме. Такой механизм соединения весьма
428 Часть I. Обработка и визуализация графов удобен с той же точки зрения, что и прямоугольная сетка для расположения объек- тов. Оба механизма позволяют симметрично располагать объекты без дополнитель- ного выравнивания. Если симметрии не требуется, то для любой линии и формы можно задать свободный режим сцепления. Тогда точки соединения других объектов можно совмещать с любой точкой данной линии или формы. В системе используется 24 вида линий и неограниченное количество форм, состав- ленных из этих линий. Формы группируются в библиотеки, позволяющие выбирать и создавать новые формы и целые подграфы. Для каждой линии и формы отдельно задаются все необходимые атрибуты, такие как цвет, толщина линии и т. д. Допуска- ется также размещение отдельно созданных изображений внутри форм и вставлений в рисунок надписей. Система SmartDraw также предоставляет ряд дополнительных возможностей, полезных при подготовке иллюстраций, например, выбор стиля всего изображения, позволяю- щий создавать выпуклые формы (см. рис. 5.53). Система отлично документирована и имеет систему подсказок, позволяющих изучить работу за очень короткое время. Система VEGRAS Система VEGRAS — это созданный в Институте систем информатики СО РАН (Но- восибирск) универсальный и простой в использовании редактор атрибутированных графов, в том числе иерархических, ориентированный на поддержку подготовки ка- чественных штриховых иллюстраций в рамках операционной среды Windows 95/98/NT. Система написана на языке C++ с использованием компилятора Microsoft Visual C++ Version 4 2 и библиотеки MFC. Вершины графа изображаются в виде различных геометрических фигур, таких как эллипс, прямоугольник, скругленный прямоугольник, ромб, треугольник или пере- вернутый треугольник. Кроме этого, каждая вершина имеет каемку (простую, жир- ную, очень жирную, пунктирную или двойную). Цвет каемки выбирается отдельно. Ребра и дуги графа изображаются либо ломаными линиями, задаваемыми точками сгиба, либо гладкими кривыми, для задания которых используется некоторый набор точек на плоскости, которые также называются точками сгиба (рис. 5.54). Линии, изображающие ребра и дуги графа, могут различаться по толщине, цвету, виду (сплошные, пунктирные) и могут снабжаться стрелками. Число точек сгиба практи- чески не ограничено. Фрагменты в системе представлены своими границами, имеющими вид "замкнутых" ребер. Все вершины и ребра графа, а также границы фрагментов могут иметь произвольное количество меток, место расположения которых пользователь может изменять. Цвет и шрифт можно задавать отдельно для каждой метки. Метки могут иметь верхние и нижние многоэтажные индексы, что весьма полезно при создании иллюстраций к научным публикациям. В процессе редактирования графа можно изменять размеры, форму, цвет вершин и дуг, перемещать и удалять вершины, дуги, метки или точки сгиба ребер и дуг, копи- ровать выделенные объекты в буфер (операции Cut, Copy, Paste), добавлять и уда- лять точки сгиба дуги. Можно выделить группу объектов графа и производить какие-
5. Визуализация 429 (бездействия сразу над всей группой (изменять цвета, форму, добавлять метки). При ом те операции, которые не добавляют и не удаляют вершины и дуги графа, меня- тлишь изображение графа, а не сам граф. Причем, само изображение графа при 1ких операциях сохраняет определенные свойства, связанные с наглядностью, частности, при перемещении вершин, дуг или точек сгиба дуги, соответствующие и метки тоже передвигаются так, чтобы их относительное месторасположение не Рис. 5.54. Система VEGRAS Полезным свойством является наличие операций Undo и Redo, позволяющих отме- нить или повторить до 32 последних действий (причем эти действия могут быть сложными, как, например, удаление группы объектов или изменение каких-либо па- раметров сразу для всей группы). В системе VEGRAS реализованы операции Zoomln/ZoomOut, позволяющие менять масштаб изображения от 1 до 1000%, и име- ется возможность использовать прямоугольную сетку, внешний вид и параметры которой можно изменять. VEGRAS позволяет записывать изображения графов в файлы форматов ОС Windows BMP и PCX, а также обеспечивает возможность вставки построенных в системе изо- бражений графов в документы других приложений, поддерживающих механизм OLE,таких как Microsoft Word и Excel. Кроме этого, система VEGRAS воспринимает формат файлов системы HIGRES, а также поддерживает конвертацию построенного (Изображения атрибутированного иерархического графа в формат системы HIGRES.
430 Часть I. Обработка и визуализация графов 5.5.3. Графовые библиотеки Библиотека LEDA Библиотека LEDA (Libraty of Efficient Data Types and Algorithms) разрабатывается совместно несколькими научными заведениями Германии с 1988 года. LEDA предна- значена для создания программ для дискретной математики. В таких программах часто требуются различные структуры данных типа стеков, очередей, словарей, по- следовательностей и т. п В этом списке не последнее место отведено графам. LEDA представляет собой набор классов и шаблонов классов на языке C++. Каждый класс моделирует некоторую структуру данных. Кроме того, существует много воз- можностей по образованию новых классов. Функции-компоненты классов реализуют алгоритмы, наиболее часто используемые для данного типа данных. Вводятся также удобные макроопределения, позволяющие расширять синтаксис C++ конструкциями типа forall. Библиотека хорошо документирована. Для каждого класса дается полная специфика- ция, включая метод реализации. Для алгоритмов даются теоретические оценки слож- ности. В LEDA входят классы, предназначенные для визуализации графов, хотя, судя по демонстрационным примерам, это решение не претендует на универсальность. Программы, использующие LEDA, можно компилировать для UNIX-платформ и для MS Windows 95/NT. LEDA распространяется как в виде исходных текстовых файлов на C++, так и в виде lib-файлов для большинства современных компиляторов. Библиотека AGD Библиотека AGD является расширением LEDA, предназначенным для рисования графов. Библиотека содержит достаточно много известных алгоритмов рисования, а также предоставляет удобные возможности для программирования новых алго- ритмов. В библиотеке описан один базовый класс, содержащий общие интерфейсные функ- ции алгоритма рисования. Для написания новых алгоритмов создаются классы, про- изводные от данного и подменяются виртуальные функции. Ряд функций класса ал- горитма обеспечивает потенциальную возможность пошаговой визуализации, если это предусмотрено самим алгоритмом. Данная библиотека может использоваться программами, создаваемыми для различ- ных платформ, в том числе Windows 95/NT. Под Windows можно использовать ком- пилятор Borland 5.x или MS Visual C++ 6.x. Процесс инсталляции библиотеки доста- точно прост. В настоящий момент AGD находится в стадии развития. Следующие версии, как со- общают авторы, будут содержать больше алгоритмов рисования графов. Библиотека снабжена достаточно подробным описанием на 134-х страницах и имеет все шансы оказаться полезной на практике.
Глава 5. Визуализация 431 Библиотека ffGraph Библиотека разработана в университете г. Пассау (Германия). FfGraph представляет собой библиотеку классов иа C++, предназначенную для создания и изображения двумерных и трехмерных графов. Основная цель библиотеки — создать удобный интерфейс для работы с графом, воз- можность привязывать к элементам графа семантическую информацию, а также ме- ханизм визуализации. Метки графов, вершин и дуг создаются как новые классы, которые могут помимо данных содержать также функции, позволяющие им взаимодействовать с другими элементами графа. В библиотеку включено два алгоритма рисования— алгоритм поуровневого изобра- жения (см. разд. 5.3) и трехмерный вариант force-метода (с.м. разд. 5.1.3). К библиотеке прилагается небольшой редактор графов, работающий под XWindow, демонстрирующий возможности библиотеки. [Подробная документация к библиотеке имеется в форматах PostScript и HTML. [Graph Drawing Server Авторы библиотеки, получившей название Graph Drawing Server, утверждают, что они разработали новую технологию, которую можно использовать для различных | задач, связанных с анимацией алгоритмов на графах. Для демонстрации этой техно- I логин, носящей название Mocha, был создан Graph Drawing Server. Суть технологии заключается в том, что на компьютере пользователя запускается Java-апплет, который позволяет редактировать граф. Изменения, производимые в графе, передаются на сервер, где они обрабатываются и по ним генерируется допол- |нительная информация, которая передается обратно клиенту, транслируясь в некото- рые действия по анимации. Например, таким способом можно вычислять выпуклую оболочку точек на плоскости. Пользователь вводит новые точки, а сервер считает их оболочку. При этом пользователь постоянно видит динамически обновляющуюся ломаную, ограничивающую выпуклую оболочку. Преимущество такого подхода за- | ключается в том, что в качестве сервера может использоваться достаточно мощный [компьютер. Таким образом любой пользователь с помощью Интернета сможет за- |пускать и анимировать сложные графовые алгоритмы. [Строго говоря, Graph Drawing Server не является системой визуализации графов, однако заслужил здесь упоминание как средство схожей направленности. [библиотеки Graph Layout Toolkit и Graph Editor Toolkit Данные библиотеки являются продуктами фирмы Tom Sawyer Software. Это единст- | венная полностью коммерческая разработка в области универсальных средств визуа- лизации графов. 1 Graph Layout Toolkit (GLT) представляет собой библиотеку на C++, включающую I компоненты рисования графов, предназначенные для интеграции в любые приложе- I ния, использующие графический интерфейс.
432 Часть I. Обработка и визуализация графов В библиотеке реализовано 4 эффективных алгоритма рисования графов, способных размещать на плоскости графы, состоящие из нескольких сотен вершин, всего за не- сколько секунд. На рис. 5.55 показан результат работы этих алгоритмов для различ- ных графов. GLT можно интегрировать в программы, разрабатываемые для различ- ных платформ, включая операционные системы Microsoft Windows, UNIX, Apple Macintosh и OS/2. Рис. 5.55. Четыре стиля расположения графа в системе GET Graph Editor Toolkit (GET) является расширением библиотеки GLT, предназначен- ным для визуализации графов в приложениях Microsoft Windows. GET построен на основе библиотеки MFC (Microsoft Foundation Classes). Так как и GLT и GET являются коммерческими разработками, они доступны только за определенную плату даже для использования в некоммерческих целях. Однако фирма Tom Sowyer Software бесплатно распространяет систему, работающую под Microsoft Windows, которая создана специально для демонстрации возможностей GLT и GET. Кроме того, существует вариант GLT и GET, а также демонстрацион- ной системы на Java, а также набор ActiveX-компонент, предоставляющий удобный API для интеграции в любые программы, работающие под ОС Microsoft Windows (рис. 5.56).
5. Визуализация 433 Рис. 5.56. Пример использования GET для ActiveX Оставшаяся часть раздела посвящена описанию системы, демонстрирующей воз- можности библиотек. Система представляет собой универсальный графовый редак- тор с некоторыми дополнениями, ориентированными на работу с графами, представ- ляющими компьютерные сети. Из описания не ясно, является ли эта ориентация ба- зовой для самих библиотек или она возникает как пример их адаптации к конкретной задаче. Система имеет удобный интерфейс и сравнительно хорошие графические возможно- сти, а также полноценную help-поддержку. Для редактирования графа используются четыре основных режима: Select, Zoom, Create Nodes, Create edges и два дополнительных: Create bends и Delete bends. Кроме основной панели инструментов в системе есть еще две — одна для выбора стиля новой вершины, другая для выбора стиля новой дуги. Вершины бывают пяти видов: □ текстовые — автоматически подстраиваются под размер текста; рисуются прямо- угольниками; О табличные — представляют из себя таблицы с одной строкой заголовка и не- сколькими строками текста в несколько линий и рядов, число которых можно из- менять; текст каждого элемента вводится отдельно; □ вершины с изображениями — содержат картинку (нужно указать файл) и подпись под ней. Размеры не меняются; □ bus— изображаются в виде горизонтальной полосы, размеры которой можно ме- нять; особенность в том, что дуги, входящие снизу и сверху, направлены не к цент- ру вершины, а перпендикулярно ее границе; текст не выводится;
434 Часть I. Обработка и визуализация графов П обычные вершины — имеют форму, выбираемую из 10-ти вариантов; можно из- менять размеры, цвет внутренности и шрифт текста. Для дуг задается стиль линии (из 9-ти вариантов), ее толщина и цвет. Кроме того, каждая дуга может иметь несколько текстовых меток. При этом метки можно произ- вольно перемещать отдельно от дуг, но каждая метка имеет несколько атрибутов, которые учитываются алгоритмами рисования. В системе существует возможность произвольного масштабирования изображения графа. Для лучшей ориентации в структуре графа можно открыть обзорное окно (рис. 5.57). Существует также возможность "сворачивания" отдельных фрагментов графа, т. е. временной замены их псевдо-вершинами для обеспечения лучшей види- мости структуры графа (рис. 5.58). Вершины графа могут содержать внутри себя дру- гие графы (рис. 5.59). Рис. 5.57. Использование обзорного окна для навигации Параметры вершин, дуг и меток дуг редактируются в специальном окне Object Properties. При этом можно изменять параметры сразу нескольких выделенных объ- ектов. В системе реализованы операции Cut, Copy, Paste для групп объектов, однако опе- рации Undo и Redo отсутствуют. Четыре алгоритма рисования, представленные в системе GLT, присутствуют в ней как четыре стиля. В зависимости от выбранного в данный момент стиля изменяется
Глава 5. Визуализация 435 Рис. 5.58. Применение механизма упрощения диаграмм путем сворачивания "фрагментов" Рис. 5.59. Пример, показывающий, что в изображениях, построенных на основе библиотек GET и GLT, вершины графа также могут быть графами
436 Часть I. Обработка и визуализация графов специфика редактирования графа. Например, если выбран стиль orthogonal, то ко- нечные звенья дуг всегда входят в вершины под прямым углом. Во всех других сти- лях они ориентируются на центр вершины. Все четыре алгоритма можно запускать на произвольном графе. При запуске алго- ритма соответственно меняется текущий стиль. Каждый алгоритм имеет некоторое множество параметров, которые можно регулировать. Существует специальный ал- горитм для размещения меток дуг. 5.5.4. Система HIGRES Система HIGRES — универсальный визуализатор и редактор иерархических графо- вых моделей (рис. 5.60), разработанный в Институте систем информатики СО РАН (Новосибирск). Основным отличием данной системы от ее аналогов является воз- можность сохранять во внутреннем представлении и визуализировать не только сам граф, но и его семантику, представленную в виде системы атрибутов вершин, фраг- ментов и дуг графа и библиотекой алгоритмов обработки — так называемых внеш- них модулей. При этом пользователь может корректировать и доопределять семанти- ку графа с помощью введения новых атрибутов и новых внешних модулей. Такой подход обеспечивает, с одной стороны, универсальность системы, с другой — воз- можность ее специализации. Система работает под ОС Microsoft Windows 95/98/NT, что выгодно отличает ее от западных аналогов, которые в подавляющем большинстве ориентированы на исполь- зование графической оболочки XWindow операционной системы UNIX. Операцион- ная система Microsoft Windows, имея предпочтительные графические возможности, гораздо шире распространена на территории России и других стран бывшего Союза. Достоинствами системы HIGRES являются качественный интуитивный интерфейс, стандартный для Windows-приложений такого типа, широкий набор графических средств визуализации, а также наличие дополнительных средств, облегчающих и ав- томатизирующих процесс редактирования графа. В настоящий момент не существует общепринятого формата файлов для хранения графов, тем более иерархических. Поэтому в системе HIGRES используется новый специальный формат. Проблема конвертации решается с помощью специальной, прилагаемой к системе, библиотеки HGL, написанной на языке C++. С ее помощью внутри любой программы можно создать иерархический граф и записать его в файл того формата, который воспринимается системой. Таким образом, HGL служит ин- терфейсным звеном между программами, генерирующими иерархические графы, и системой HIGRES, выступающей в роли их визуализатора. При визуализации автоматически сгенерированных графов всегда встает проблема их автоматического расположения на плоскости. Это расположение в общем случае должно быть наиболее удобным для пользователя, т. е. пользователь должен полу- чать из него как можно лучшее представление о структуре графа. В зависимости от семантики графа к этому требованию могут добавляться и более специфические, на- пример можно требовать расположить рядом какую-нибудь пару семантически свя- занных вершин. Проблема автоматического расположения графа на плоскости реша-
Глава 5. Визуализация 437 ется с помощью так называемых методов рисования графов. В систему HIGRES включено несколько таких методов. Система позволяет воздавать качественные изображения графов и записывать их в файлы форматов ОС Windows BMP и PCX. Последний формат может служить для создания иллюстративного материала для книг и статей, подготовленных в системе ТеХ. Важной особенностью системы HIGRES является поддержка ею визуальной обра- ботки иерархических графовых моделей. Для этого в системе имеется возможность визуализации процесса исполнения любого ее внешнего модуля и предусмотрены средства, позволяющие легко расширять систему библиотеками модулей, создавае- мыми пользователями в соответствии со своими индивидуальными потребностями. Рис. 5.60. Иерархический граф в системе HIGRES Визуализация графовой модели и интерфейс Визуализация графа в системе HIGRES организована таким образом, чтобы макси- мально наглядно изобразить как иерархическую структуру графа, так и его се- мантику. Каждому фрагменту графа соответствует некоторый прямоугольник плоскости, внутри которого располагаются все его вершины. Кроме того, для каждого фрагмента можно открыть отдельное окно, в котором видны только вершины данного фрагмен- та и его подфрагменты. При этом каждый подфрагмент можно объявить закрытым — тогда изображаются только его контуры, либо открытым — тогда изображаются все его вершины и инцидентные им дуги. Для изображения контуров фрагментов в сис-
438 Часть I. Обработка и визуализация графов теме используется прием создания эффекта тени. Закрытые фрагменты выглядят слегка выступающими вверх — как будто они закрыты крышками, открытые же слегка утоплены вниз. Для изображения вершин используется несколько вариантов геометрических фигур. Кроме того, можно выбирать стиль и цвет контура и заливки вершины. Эти парамет- ры задаются отдельно для каждого типа вершин. Таким образом, вершины, принад- лежащие к одному типу, визуально похожи друг на друга, хотя могут отличаться тек- стом меток. Ребра (дуги) графа изображаются либо ломаными линиями, задаваемыми точками сгиба, либо гладкими кривыми, для задания которых также используется некоторый набор точек на плоскости, вдоль которых проходит дуга (эти точки по аналогии так- же называются точками сгиба). Вариант изображения дуги, стиль ее линии и стиль стрелки на конце (если граф ориентированный) задается отдельно для каждого типа дуг. Для визуализации атрибутов объектов (вершин, ребер, фрагментов) используется гибкая система, позволяющая изображать их не просто как список значений меток, а более наглядным и естественным образом. Для каждого типа объектов задается "строка визуализации", представляющая собой шаблон текста, изображающего атри- буты каждого объекта данного типа. В этой строке определяются места, в которые при визуализации подставляются значения меток конкретного объекта. Кроме того, строка может содержать специальные символы, отмечающие места начала новой строки. В конечном итоге для каждого объекта определяется некоторый текст, кото- рый называется текстом меток. Более точно, для типов вершин задаются две строки визуализации и соответственно два текста меток: внутренний и внешний. При визуа- лизации вершины внутренний текст меток располагается внутри нее, а внешний ря- дом с ней. Точно так же для типов фрагментов задаются две строки визуализации, порождающих "закрытый" и "открытый" текст меток. Первый изображается внутри фрагмента, когда он закрыт, а второй — когда открыт. Единственная строка визуали- зации, задаваемая для каждого типа дуг, порождает текст меток для каждой дуги данного типа, который располагается рядом с одной из точек сгиба дуги либо рядом с одной из конечных точек данной дуги. Интерфейс системы придерживается основных общепринятых стандартов для при- ложений ОС Windows 95. Система имеет главное окно, внутри которого расположе- ны окна фрагментов, которые пользователь может открывать и закрывать по мере надобности, переходя вверх и вниз по иерархии. Главное окно системы содержит меню и toolbar, обеспечивающий быстрый доступ к часто используемым операциям. Пользователь может переключаться с режима просмотра на режим редактирования графа. В режиме просмотра можно только открывать и закрывать фрагменты графа и их окна, просматривая содержимое, прокручивать изображение в окнах и изменять его масштаб. В режиме редактирования левая кнопка мыши служит для выделения объектов, а правая для высвечивания всплывающего меню, с помощью которого можно выбрать операцию, производимую с выделенным объектом. Кроме того, вы- брав соответствующий пункт в этом меню, можно добавить в граф новую вершину, фрагмент или дугу (рис. 5.61). С помощью левой кнопки мыши пользователь может перемещать вершины, фрагменты и сгибы дуг, а также изменять размеры вершин и
Глава 5. Визуализация 439 границы фрагментов. При этом никакие две вершины не должны накладываться друг на друга и каждый фрагмент должен целиком включать в себя все свои вершины и подфрагменты. По желанию пользователя система может либо автоматически кор- ректировать расположение графа после каждого изменения его пользователем, так чтобы это условие выполнялось, либо просто запретить нарушающие его переме- щения. Существуют также два дополнительных режима редактирования, использование которых может ускорить выполнение некоторых часто производимых операций, — режим создания объектов и режим редактирования меток. Рис. 5.61. Редактирование графа в системе HIGRES Визуальная обработка графов С точки зрения пользователя, процесс визуальной обработки иерархического графа в системе HIGRES выглядит следующим образом Пользователь с помощью системы выбирает нужный ему внешний модуль (например, определенный алгоритм автома- тического размещения графа на плоскости) и запускает его. Система передает теку- щий граф обрабатывающему модулю и открывает специальное окно, предоставляю- щее пользователю интерфейс для управления работой модуля. Пользователь может регулировать параметры обработки, прерывать ее на любом шаге, просматривать промежуточные результаты в любую сторону в форме анимации либо в покадровом режиме. Анимация алгоритмов, поддерживаемая системой HIGRES, может быть использована для их тестирования и отладки, для образовательных целей, а также для изучения
440 Часть I. Обработка и визуализация графов итеративных процесов, возникающих, например, в некоторых методах рисования графов. Для каждого модуля определяется набор числовых и текстовых параметров, которые пользователь может изменять в процессе работы. Кроме того, модуль может сам инициировать запрос необходимых ему данных, а также генерировать сообщения, которые вместе с другой рабочей информацией записываются в протокол, выдавае- мый на экран. В системе существует возможность расширения путем добавления новых модулей двух типов. Во-первых, это модули, содержащие алгоритмы размещения графов на плоскости. Во-вторых, это модули, с помощью которых можно производить семан- тическую визуальную обработку графовых моделей, т. е. выполнять любые алгорит- мы на графах визуально наблюдая результат каждого шага алгоритма От программиста, создающего свой собственный внешний модуль, не требуется зна- ния деталей внутреннего представления иерархических графов в системе, поскольку все взаимодействие внешнего модуля с системой обеспечивается функциями библио- теки HGL. Создавая модуль, программист должен позаботиться, кроме программиро- вания непосредственно самого процесса обработки, лишь о разбиении этого процесса на шаги, число которых не фиксируется. Внешний модуль представляет собой от- дельное Windows-приложение и может быть получен с использованием любого ком- пилятора C++ для ОС Windows, понимающего шаблоны классов. Библиографический комментарий Интерес к вопросам визуальной обработки и к неклассичсским графовым формализмам замет- но возрос в 80-е годы XX века в связи с широким распространением рабочих станций. В на- стоящее время вопросам визуальной обработки графов и графовых моделей посвящена об- ширная литература. Известный обзор [32] результатов по рисованию графов (graph drawing) содержит более 300 работ, написанных до 1993 года. С 1994 года ежегодно по этой тематике делается более 100 докладов на международных конференциях, посвященных вопросам рисо- вания графов. Материалы этих конференций публикуются в серии книг Lecture Notes in Computer Science. Хорошим введением в проблематику рисования графов являются книги [33, 37]. Первый алгоритм проверки планарности графа был разработан в работах [10. 531. Хопкрофт и Тарьян улучшили этот результат до линейного времени [61. 85]. Другой линейный алгоритм проверки планарности графа, рассмотренный нами, был предложен в [17, 75]. Обзоры методов рисования планарных графов и преобразования графа в планарный содержатся в |107|. В [17. 76] дается доказательство ДТ+полноты достижения планарности графа путем удаления или расщипления минимального числа его вершин. Использование техники нахождения в сети потока минимальной стоимости для построения более качественных ортогональных изображений впервые было предложено Тамасся [98—99], а затем расширено в работах [48, 100—101]. Обзор мето юв ортогонального изображения гра- фов содержится в [42|. Обзор методов рисования деревьев и последовательно-параллельных графов содержится в [88]. В работе [25] описан метод Чана для построения изображения бинарных деревьев в об- ласти почти линейного размера. Статья [59] содержит описание методов изображения после-
Глава 5. Визуализация 441 довательно-иараллсльных графов. Метод, позволяющий за линейное время распознать и скон- струировать бинарное дерево разбора для последовательно-параллельного графа, изложен в [I04J. Первой работой по использованию физического моделирования при рисовании графов счита- ется небольшая заметка [38], хотя аналогичные решения уже до этого были описаны как в приложениях, в контексте построения печатных схем [47, 92], так в исследованиях по чистой матемагике [102—1031 В настоящее время существует большое разнообразие методов в рам ках этого подхода и исследований их эффективности по отношению к задачам визуализации разных классов графов [13—14, 19. 21. 31, 40. 44, 50, 71, 81, 87|. Обзор методов построения изображений графов с использованием физических аналогий содержится в [20]. Первоначально идея поуровневого (иерархического) изображения графа была сформулирована еще в 1981 году [97], а закже в некоторых других очень близких по тематике работах [25, 106] Дальнейшее развитие (см. аннотированную библиографию [32]) сохранило основную концеп- цию, в которой данный подход содержит три части, выделенные Сугиямой. Хотя некоторые исследователи склонны выделял ь задачу проведения ребер в отдельный этап алгоритма. В этих случаях ребра изображаются нс каноническими ломанными. а, например, сплайнами [52, 94]. Для проведения сплайнов, не пересекающих вершины графа и проходящих через заданные области плоскости, существует алгоритм описанный в [35]. Также задача проведения ребер иногда выделяется в отдельный этап, если вершины графа имеют поточечное представление [94]. Проблема оптимальной расстановки меток на дугах графа применительно к иерархиче- скому размещению рассмотрена в (65]. В работах [16, 29] рассмотрены разные подходы к ин- крементальному размещению ациклических графов. Технике разнесения вершин по уровням и вставке фиктивных вершин посвящены работы [28, 49, 52, 73, 78]. Задача определения порядка расположения вершин на каждом уровне с целью минимизации пересечений ребер формули- руется в виде задачи целочисленного npoi раммирования как в случае двух уровней [57, 62], так и глобально— сразу для всех уровней [64, 105]. Сравнению различных методов миними- зации пересечений посвящено сразу несколько работ [39, 63, 83—84]. Другим аспектам по- уровневого подхода посвящены работы [1, 11, 56]. Одним из первых "неклассических" графовых формализмов явились гиперграфы [15]. Однако гиперграфы не охватывают иерархичность структурных объектов, и в 1988 году на базе гипер- графов Харел [55] сформулировал более общий графовый формализм, названный "хиграфами (higraphs). Хиграфы могут представлять сложные отношения между объектами с использова- нием так называемых "пятен" (blobs), которые могут быть многоуровневыми и могут как включать, так и пересекать друг друга. Сугияма и Мисуе [96] предложили формализм, назван- ный "составными" графами (compound digraphs), который расширил класс ориентированных графов. Составные графы допускают между вершинами отношения как смежности, так и включения но образуют более узкий класс, чем хиграфы. Фенг, Коен и Иэдес [46] предложили так называемые "кластерные" графы (clustered graphs), которые являются естественным обоб- щением неориентированных графов на модели, имеющие иерархическую структуру, и хорошо подходят к решению задач рисования. Обзор методов рисования кластерньгх и составньгх гра- фов содержится в [24]. Рассмотренные в разд. 5.4 иерархические графы и графовые модели были предложены В. Н. Касьяновым [2—4, 68—70]. Исследованиями вопросов преобразования графов занимается теория графовых грамматик и систем переписывания графов Знакомство с этим активно развивающимся направлением можно начать с работ [30, 89]. Для подробного рассмотрения в рамках данной главы были отобраны наиболее известные на сегодняшний день универсальные средства визуализации графов. Наиболее полный список систем и библиотек, относящихся в той или иной мере к данной области, можно найти в [8] и [108]. Там же можно найти ссылки на Web-страницы, позволяющие непосредственно познако-
442 Часть I. Обработка и визуализация графов мяться с возможностями рассмотренных систем. Среди множества публикаций, посвященных средствам визуализации графов, можно указать статьи, в которых описываются следующие рассмотренные нами системы и библиотеки: [51]— daVinchi, [94]— VCG, [58] — GraphEd, [59] — GraphLet. [74] — GraVis, [23] — Graph Drawing Server, [36, 82] — GLT и GET, [6, 9] — VEGRAS, [5—8, 80] — HIGRES. Имеется ряд направлений, связанных с тематикой рисования графов. Топологическая теория графов изучает вложения графов в пространство. Хорошим введением в эту область является [54]. Обзор алгоритмов и нижних границ для числа пересечений при разных вложениях содер- жится в [95]. Геометрическая теория графов изучает комбинаторные и геометрические свойст- ва прямолинейных изображений — например, см. [67, 91]. Родственные изображения пред- ставляют графы посредством родственных отношений, например, можно изобразить дерево как Евклидовое минимальное покрывающее дерево множества точек на плоскости. Обзор это- го направления содержится в [34]; среди более поздних работ можно назвать [18, 41, 43, 76. 79]. Изображения пересечений и касаний представляют графы посредством отношений пере- сечения и касания между геометрическими фигурами [22, 72, 86]. Список литературы 1. Бабурин Д. Е. Иерархический подход для автоматического размещения ациклических графов // Современные проблемы конструирования программ. Новосибирск: ИСИ СО РАН, 2002. — С. 7—37. 2. Касьянов В. Н. Иерархические графы и графовые модели: вопросы визуальной обработки // Проблемы систем информатики и программирования. — Новосибирск: ИСИ СО РАН, 1999. —С 7—32 3. Касьянов В Н Применение графов в программировании // Программирование. — 2001. —№3 —С. 51—70. 4. Касьянов В. Н. Средства поддержки применения графов в программировании // Проблемы программирования. — 2000. — № 1—2. — С. 286—300. 5. Лисицын И. А. Применение системы HIGRES для визуальной обработки иерархических графовых моделей // Проблемы систем информатики и программирования. — Новоси- бирск, 1999. — С. 64—77. 6. Лисицын И А. Организация графического вывода в системе визуализации иерархических графовых моделей // Поддержка супервычислений и интернет-ориентированные техноло- гии. — Новосибирск, 2001. -— С. 193—210 7. Лисицын И. А. Организация пользовательского интерфейса в системе визуализации иерархических графовых систем // Поддержка супервычислений и интернет-ориенти- рованные технологии. — Новосибирск, 2001. — С. 211—221. 8. Лисицын И. А. Системы визуализации и редактирования графовых объектов. — Новоси- бирск, 2000. — 40 С. —- (Препринт ИСИ СО РАН, № 76). 9. Мердишева Т. С., Мердишева Е. С. Подготовка графовых иллюстраций с помощью сис- темы VEGRAS // Поддержка супервычислений и интернет-ориентированные техноло- гии. — Новосибирск, 2001. — С. 222—229 10. Auslander L , Parter Т. V. On imbedding graphs in the plane // J. Math and Meeh. — 1961. — Vol. 10, —P. 517—523. 11. Baburin D. E. Using graph based representations in reengineering // Proc, of Sixth European Conf, on Software Maintenance and Reengineering. — IEEE Computer Society Press, 2002. — P. 203—206.
Глава 5. Визуализация 443 12. Ball Т., Eick S. Software visualization in large // IEEE Computer. — 1996. — Vol. 29, N 4. — P. 25—39. 13. Becker B., Hotz G. On the optimal layout of planar graphs with fixed boundary // SIAM J Comput. — 1987. — Vol. 16, N 5. — P. 946—972. 14. Bentley J., Ottman T. Algorithms for reporting and counting geometric intersections // IEEE Trans. Comput. — 1979. — Vol. 28. — P. 643—647. 15. Berge C. Graphs and hypergraphs. — North-Holland, 1973. 16. Bohringer K., Paulisch F. N. Using constraints to achieve stability in automatic graph layout al- gorithms // Proc, of the ACM CHl’90. — 1990. — P. 43—51. 17. Booth K., Lueker G. Testing for the consecutive ones property interval graphs and graph planar- ity using PQ-tree algorithms I I J. Comput. Syst. Sci. — 1976. — Vol. 13. — P. 335—379. 18. Bose P., Lenhart W., Liotta G. Characterizing proximity trees // Algorithmica.— 1996.— Vol. 16. —P. 83—110. 19. Brandenburg F. J., llimsolt M., Rohrer C. An experimental comparison of force-directed and randomized graph drawing algorithms // Leet. Notes Comput. Sci.— 1996.— Vol. 1027.— P. 76—87. 20. Brandes U. Drawing on physical analogies // Lecture Notes Comput. Sci.— 2001.— Vol. 2025, —P. 71—86. 21. Branke J., Bucher F., Schmeck 11. Using genetic algorithms for drawing undirected graphs // Proc, of the Third Nordic Workshop on Genetic Algorithms and their Applications (3NWGA). — 1997. — P. 193—205. 22. Breu H., Kirkpatrick D. G. Unit disk graph recognition is NP-hard // Comput. Geom. Theory Appl. — 1998. — Vol. 9, N 1—2. — P. 3—25. 23. Bridgeman S., Garg A., Tamassia R. A graph drawing and translation service on the WWW // Leet. Notes Comput. Sci. — 1996. — Vol. 1190. —P. 45—52. 24. Brockenauer R., Cornelsen S. Drawing clusters and hierarchies // Leet. Notes Comput. Sci. — 2001. — Vol. 2025. — P. 193—227. 25. Carpano M. .1. Automatic display of hierarchized graphs for computer aided decision analysis // IEEE Trans. Syst. Man Cybern. — 1980. — Vol. 10, N 11. — P. 705—715. 26. Chan T. M. A near-linear area bound for drawing binary trees // Proc, of the 10lh ACM-S1AM Symp. On Discrete Algorithms. — 1999. — P. 161—168. 27. Chazelle B.,.Edelsbrunner H. An optimal algorithm for intersecting line segments in the plane // JACM. — 1992. — Vol. 39, N. I. —P. 1—54. 28. Coffman E. G., Graham R. L. Optimal scheduling for two processor systems // Acta Infor- matics — 1972. — Vol. 1. — P. 200—213. 29. Cohen R. F., De Battista G., Tamassia R., Tollis 1. G. Dynamic graph drawings: trees, series- parallel digraphs, and planar st-graphs // SIAM .1. Comput.— 1995.— Vol. 24, N 5.— P. 970—1001. 30. Computing by graph transformation. A survey and annotated bibliography / Ed. by H.Ehrig, G.Taentzer// Bulletin of the EATCS. — 1996. — N 59. — P. 182—226. 31. Cruz I. F., Twarog J. P. 3D Graph drawing with simulated annealing //Leet. Notes Comput. Sci.—1996. —Vol. 1027. —P. 162—165. 32. Di Battista G., Eades P., Tamassia R., Tollis I. Algorithms for drawing graphs: an annotated bib- liography // Computational Geometry Theory. — 1994. — Vol. 4, N 5. — P. 235—282.
444 Часть I. Обработка и визуализация графов 33. Di Battista G., Eades P., Tamassia R., Tollis I. G. Graph Drawing: Algorithms for Vizualization of Graphs. — Prentice Hall, 1999. 34. Di Battista G., Lenhart W., Liotta G. Proximity drawability: a survey // Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 328—339. 35. Dobkin D. P., Gasner E. R., Koutsofios E., North S. C. Implementing a general-purpose edge router // Proc, of the Symposium on Graph Drawing GD’97. — Leet. Notes Comput. Sci. — 1998, —Vol. 1353. —P. 262—271. 36. Dogrusoz U., Madden B., Madden P. Circular layout in the graph layout toolkit // Leet. Notes Comput. Sci. — 1996. — Vol. 1190. — P. 92—100. 37. Drawing Graphs. Methods and Models. — Berlin: Springer, 2001. — (Leet. Notes Comput. Sci.; 2025). 38. Eades P. A heuristic for graph drawing 11 Congressus Numerantium. — 1984. — Vol. 42. — P. 149—160. 39. Eades P., Kelly D. Heurisitcs for reducing crossings in 2-layered networks // Ars Combin. — 1986. — Vol. 21. — P. 89—98. 40. Eades P., Lin T., Lin X. Minimum size h-v drawings // World Scientific. — 1992. — Ser. in Comput. Sci. — Vol. 36. — P. 386—394. 41. Eades P_, Whitesides S. The realization problem for Euclidean minimum Spanning trees is NP-hard 11 Algorithmica. — 1996. — Vol. 16. — P. 60—82. 42. Eiglsperger M_, Fekete S. P. ,Klau G. W. Orthogonal graph drawing // Leet. Notes Comput. Sci. —2001. —Vol. 2025. —P. 121—171. 43. El-Gindy H., Liotta G., Lubiw A., Meijer H., Whitesides S. H. Recognizing rectangle of influ- ence drawable graphs // Lect.Notes Comput. Sci. — 1995. — Vol. 894. — P. 352—363. 44. Erlingsson U., Krishnanioorthy M. Interactive graph drawing on the world wide web // Sixth World Wide Web Conference. — 1997. 45. Faria L. D., De Figueiredo С. M. H., Mendonce C. F. X. Splitting number is NP-complete // Leet. Notes Comput. Sci. — 1998. — Vol. 1517. — P. 285—297. 46. Feng Q., Cohen R. F.. Eades P. Planarity for clustered graphs // Leet. Notes in Comput. Sci. — 1995. — Vol. 979. — P. 213—226. 47. Fisk C. .1., Caskey D. L., West L. E. ACCEL: Automated circuit card etching layout // Proc, of the IEEE.— 1967. — Vol. 55, N IL — P. 1971—1982. 48. FoBmeier U. Interactive orthogonal graph drawing: algorithms and bounds // Leet. Notes Corn- put. Sci. — 1997. — P. 11—123. 49. Frick A. Upper bounds on the number of hidden nodes in Sugiyama’s algorithm // Proc, of the Symposium on Graph Drawing GD’96. — Leet. Notes Comput. Sci. — 1997. — Vol. 1190.— P. 169—183. 50. Frick A.. Ltidwig A., Mehldau H. A Fast Adaptive Layout Algorithm for Undirected Graphs// Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 388—403. 51. Frohlich M., Werner M. Demonstration of the Interactive Graph-Visualization System daVinci// Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 266—269. 52. Gasner E. R., Koutsofios E., North S. C., Vo К. P. A technique for drawing directed graphs// IEEE Transactions on Software Engineering. — 1993. — Vol. 19. N. 3. — P. 214—230. 53. Goldstein A. J. An efficient and constructive algorithm for testing whether a graph can be embedded in the plane //Graph and Combinatorics Conf. — 1963.
Глава 5. Визуализация 445 54. Gross J. L., Tucker Г. W. Topological Graph Theory. — John Wiley & Sons, 1987. 55. Harel D. On visual formalisms // Comm, of the ACM. — 1988. — Vol. 31, N 5. — P. 514— 530. 56. He W., Marriott K. Constrained graph layout // Leet. Notes Comput. Sci.— 1997.— Vol. 1190.— P. 217—233. 57. Healy P., Kuusik A. The vertex-exchange graph: a new concept for multi-level crossing mini- mization // Leet. Notes Comput. Sci. — 1999. — Vol. 1731. — P. 205—216. 58. Himsolt M. GraphEd: a graphical platform for the implementation of graph algorithms // Leet. Notes Comput. Sci.— 1994. — Vol. 894.—P. 182—193. 59. Himsolt M. The Graphlet system (system demonstration) // Leet. Notes Comput. Sci. — 1996. — Vol. 1190. — P. 233—240. 60. Hong S.-H., Eades P„ Quigley A., Lee S.-H. Drawing algorithm for series-parallel digraphs in two and tree dimensions // Leet. Notes Comput. Sci. — 1998. — Vol. 1547. — P. 198—209. 61. Ilopcroft J., Tarjan R. E. Efficient plananty testing // J. ACM.— 1974.— Vol. 21. N 4.— P. 549—568. 62. Junger M., Lee E. K.. Mutzel P.. Odenthal '1'. A polyhedral approach to the multi-layer crossing minimization problem // Leet. Notes Comput. Sci. — 1998. — Vol. 1353. — P. 13—124. 63. Junger M., Mutzel P. 2-layer straight-line crossing minimization: performance of exact and heu- ristic algorithms // J. on Graph Algorithms and Applications. — 1997. — Vol. 1, N. 1. — P. 1— 25. 64. Junger M., Mutzel P. Exact and heuristic algorithms for 2-layer straight-line crossing minimiza- tion // Leet. Notes Comput. Sci. — 1995. — Vol. 1027. — P. 337—348. 65. Kakoulis K. G., Tollis I. G. An algorithm for labeling edges of hierarchical drawings // Leet. Notes Comput. Sci. — 1997. — Vol. 1353.— P. 169—180. 66. Kamada T., Kawai S. An algorithm for drawing general undirected graphs // Inf. Processing Lett.— 1989.— Vol. 31, N L — P. 7—15. 67. Karolyi G_, Pach .1., Toth G., Valtr P. Ramsey-Type Theorems for geometric graphs // Proc. 13th Annu. ACM Sympos. Comput. Geom. — 1997. — P. 94—103. 68. Kasyanov V. N. Hierarchical graphs and visual processing // Intern. Congress of Mathematicians (1CM98). Abstracts of Short Communications and Poster Sessions. — Berlin, 1998. — P. 292. 69. Kasyanov V. N., Lisitsyn 1. A. Hierarchical graph models and visual processing // Proc, of In- tern. Conf, on Software: Theory and Practice (ICS-2000). 16th IF1P World Computer Con- gress. — Beijing, 2000. — P. 179—182. 70. Kasyanov V. N„ Lisitsyn I. A. Support tools for hierarchical information visualization // Human- Computer Interaction: Communication, Cooperation and Application Design. — Lawrence Erlbaum Associates PubL, London. 1999. — Vol. 2. — P. 117—121. 71. Kosak C., Marks J. A parallel genetic algorithm for network-diagram layout // Proc. 4th Internal. Conf, on Genetic Algorithms. — 1991. 72. Kratochvil J., Matousek J. Intersection graphs of segments // J. Combin. Theory Ser. B. — 1994. — Vol. 35, N 2. — P. 317—339. 73. Lam S., Sethi R. Worst case analysis of two scheduling algorithms // SIAM J. on Computing. — 1977, —Vol. 6, N. 3. 74. Lauer H., Ellrich M., Soukup K. GraVis — system demonstration // Leet. Notes Comput. Sci. — 1997. — Vol. 1353. — P. 344—349.
446 Часть I. Обработка и визуализация графов 75. Lempel A., Even S., Cederbaum I. An algorithm for planarity testing of graphs // Theory of Graphs: Internal. Symposium. —New York, 1967. — P. 215—232. 76. Lenhart W., Liotta G. Proximity drawings of outerplanar graphs // Leet. Notes Comput. Sci. — 1997. — Vol. 1190. — P. 286—302. 77. Lewis J. M., Yannakakis M. The node-detection problem for hereditary properties is NP-comp- lete // J. Comput. and System Sci. — 1980. — Vol. 20, N 2. — P. 219—230. 78. Lin X. Analysis of algorithms for drawing graphs: PhD thesis — Dep. of Comput. Sci. Univ, of Queensland. — 1992. 79. Liotta G., Tamassia R., Tollis 1. G., Vocca P. Area requirement of gabriel drawings // Leet. Notes Comput. Sci. — 1997. — Vol. 1203. — P. 135—146. 80. Lisitsyn 1. A., Kasyanov V. N. HIGRES — visualization system for clustered graphs and graph algorithms // Lecture Notes in Computer Science. — 1999. —Vol. 1731. — P. 82—89. 81. Luders P., Ernst R., Stille S. An approach to automatic display layout using combinatorial opti- mization//Software-Practice and Experience.— 1995. — Vol. 25, N IL-—P. 1183—1202. 82. Madden B., Madden P., Powers S., Himsolt M. Portable graph layout and editing // Leet. Notes Comput. Sci. — 1995. —Vol. 1027. —P. 385—395. 83. Makinen E. Experiments on drawing 2-level hierarchical graphs // Inter. J. of Comput. and Mathematics. — 1990. — Vol. 36. — P. 175—181. 84. Maluszewski C., Schonfeld R., Molitor P. Using sifting for к-layer straightline crossing minimi- zation // Leet. Notes Comput. Sci. — 1999. — Vol. 1731. — P. 205—216. 85. Mehlhom K., Mutzel P. On the Embedding Phase of the Hopcroft and Taijan Planarity Testing Algorithm // Algorithmica. — 1996. — Vol. 16. — P. 233—242. 86. Mohar B. A polynomial time circle packing algorithm // Discrete Math.— 1993.— Vol. 117. —P. 257—263. 87. Monien B., Ranune F., Salmen H. A parallel simulated annealing algorithm for generating 3D layouts of undirected graphs // Leet. Notes Comput. Sci. — 1996. — Vol. 1027. — P. 396— 408. 88. Muller-Hannenmann M. Drawing trees, series-parallel digraphs, and Lattices // Leet. Notes Comput. Sci. — 2001. — Vol. 2025. — P. 46—70. 89. Nagi M. A tutorial and bibliographical survey of graph grammars // Leet. Notes in Comput. Sci. — 1980. — Vol. 73. — P. 70—126. 90. North S. Incremental layout in DynaDAG // Leet. Notes Comput. Sci.— 1996.— Vol. 1027, —P. 409—418. 91. Pach .1., Shahrokhi F., Szegedy M. Applications of the crossing number // Algorithmica.— 1996, —Vol. 16, —P. 111—117. 92. Quinn N. R., Jr., Breuer M. A. A forced directed component placement procedure for printed circuit boards // IEEE Transactions on Circuits and Systems.— 1979.— CAS-26, N 6.— P. 377—388. 93. Rosenstiehl P., Tarjan R. E. Rectilinear planar layouts and bipolar orientations of planar graphs // Discrete Comput. Geom. — 1986. — Vol. 1, N 4. — P. 343—353. 94. Sander G. Graph layout through the VCG tool // Leet. Notes Comput. Sci.— 1995.— Vol. 894. —P. 194—205. 95. Shahrokhi F., Szekely L. A., Vrt'o I. Crossing numbers of graphs, lower bound techniques and algorithms: a survey // Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 131—142.
Глава 5. Визуализация 447 96. Sugiyama К., Misue К. Visualization of structural! information: automatic drawing of com- pound digraphs // IEEE Trans on Systems, Man and Cybernetics. — 1991 - Vol. 21, N 4. — P. 876—892. 97. Sugiyama K., Tagawa S., Toda M. Methods for visual understanding of hierarchical systems // lEEETrans Syst., Man and Cybern.— 1981. — Vol. 11. N 2. — P 109—125. 98. Tamassia R. New layout techniques for entity-relationship diagrams // Proc. 4th Internal. Conf, on Entity-Relationship Approach. — 1985. — P. 304—311 99. Tamassia R. On embedding a graph in the grid with the minimum number of bends // SIAM J. Comput. — 1987. —Vol. 16, N3. — P. 421—444. 100. Tamassia R., Tollis I. G., Vitter J. S. Lower bounds and parallel algorithms for planar orthogo- nal grid drawings// Proc. IEEE Symposium on Parallel and Distributed Processing. — 1991. — P. 386—393 101 Tamassia R., Tollis 1. G., Vitter J. S. Lower bounds for planar orthogonal drawings of graphs // Inform Process. Lett.— 1991 Vol 39. — P. 35—40. 102. Tutte W. T. Convex representations of graphs // Proc. London Math. Soc. — 1960. — Vol. 10, N 3. — P. 304—320. 103. Tutte W. T. How to draw a graph // Proc. London Math. Soc. — 1963. — Vol. 13. N 3. — P. 743—768. 104 Valdes J., Tarjan R. E., Lawler E. L. The recognition of series-parallel digraphs // SIAM .1. Comput. — 1982. — Vol. 11, N 2. — P. 298—313. 105 Vahant L. Universality considerations in VLSI circuits // IEEE Trans. Comput.— 1981 C-30, N 2. — P. 135—140. 106 Warfield .1. Crossing theory and hierarchy mapping // IEEE Trans. Syst., Man and Cybern. — 1977. — Vol. 7, N. 7 — P. 502—523. 107. Weiskircher R. Drawing planar graphs // Leet. Notes Comput. Sci. — 2001. — Vol. 2025. — P. 23—45. 108. Willhalm T. Software packages // Leet. Notes Comput. Sci., 2001. — Vol. 2025. — P. 274— 282.
ЧАСТЬ II Применение графов и граф-моделей Глава 6. Информационные деревья Глава 7. Синтаксические деревья Глава 8. Контекстный анализ Глава 9. Кодогенерация Глава 10. Потоковый анализ программ Глава 11. Преобразование программ Глава 12. Прочие граф-модели 15 Зак. 202
В данной части, состоящей из 7 глав, описываются основные приложения графов и граф-моделей в программировании. В ней подробно рассмотрены использования графовых моделей в таких основных областях приложения, как хранение и поиск информации, трансляция и оптимизация программ, анализ, преобразование и распараллеливание программ, параллельная и рас- пределенная обработка информации. В главе 6, начинающей данную часть, рассматриваются информационные деревья, под которыми понимаются одномерные и многомерные структуры данных. Сюда включены сведения о таких деревьях для хранения и поиска информации, как /lfi/7-деревья, 2-3 деревья, В-деревья и т. д. В главе 7 изучаются синтаксические деревья. Ставятся задачи синтаксиче- ского и лексического анализа, рассматриваются порождающие грамматики, перевод и конструкторы анализаторов. Глава 8 посвящена контекстному анализу. В ней излагаются сведения об ат- рибутных грамматиках, конструировании абстрактных синтаксических пред- ставлений. Рассматриваются основные подклассы атрибутных грамматик и вычислений, L-атрибутные грамматики, распределение памяти под атри- буты. В главе 9 рассматривается кодогенерация. Глава содержит следующие разде- лы: задача кодогенерации и объектная машина, управление памятью периода исполнения, линейные участки и управляющие графы, простой кодогенера- тор, распределение и присваивание регистров, представление лучей дэгами, алгоритм кодогенерации, основанный на динамическом программировании, генерация кодогенераторов, генерация оптимального кода для стековых машин. Глава 10 посвящена потоковому анализу программ. В ней рассматривают- ся такие вопросы, как анализ потока управления, гамачное представление управляющих графов, отношения обязательного предшествования и обяза- тельной преемственности, структурная сложность программы, анализ потока данных. В главе 11 рассматриваются преобразования программ. Подробно описыва- ются вопросы, связанные с унификацией и системами переписывания тер- мов, с промежуточными представлениями и операторными моделями про- грамм. Глава 12 содержит материал о некоторых основных граф-моделях, исполь- зуемых в программировании. Это — диаграммы бинарных решений, частич- но упорядоченные множества, сети Петри и графы адресуемых данных.
ГЛАВА 6 Информационные деревья В программировании часто приходится иметь дело с необходимостью хранения ди- намических информационных множеств, состоящих из однотипных элементов, меж- ду которыми нет никаких отношений. Разные приложения используют различные наборы операций. Нередко, например, требуется лишь добавлять или удалять эле- менты, а также проверять, принадлежит ли множеству данный элемент. Обычно элементы информационного множества — это объект сложной природы и с внутренней структурой, поэтому для эффективной работы с ними каждому элементу ставится в соответствие (взаимнооднозначно) так называемый ключ— информаци- онный элемент без внутренней структуры. Замена прямого поиска по элементу поис- ком элемента по ключу, имеющим более простую природу, позволяет сделать поиск более эффективным. При этом, информационному множеству могут сопоставляться один или несколько систем ключей, причем в разных приложениях они могут разли- чаться. В простейшем случае в качестве ключа может рассматриваться некоторая часть информационного элемента. Заметим, что поиск по ключу иногда называют ассоциативным поиском, а информа- ционное множество с введенной системой ключей— информационным массивом или словарем. В силу того, что информационное множество может пополняться произвольным об- разом, система ключей должна быть выбрана так, чтобы любые мыслимые элементы информационного множества имели бы разные ключи. Это означает, что совокуп- ность ключей текущего состояния информационного множества всегда является подмножеством некоторой генеральной совокупности ключей. В качестве системы ключей всегда выбирается такая, для которой между ключами существует некоторое естественное отношение. Это означает, что приписывание элементам информационного множества ключей вводит в него, как правило, некото- рую структуру. Эта структура используется для регуляризации операций над инфор- мационными множествами. Существует широкий набор типов структурированных информационных множеств, связанных, как правило, с двумя типами отношений между ключами. К первому от- носятся разбиения всей генеральной совокупности на конечное число классов зкви-
452 Часть II. Применение графов и граф-моделей валентных, и этот тип порождает такие структуры, часто называемые хэш-таблицами (или таблицами расстановки), как таблицы с оглавлением и перемешанные таблицы. Этот тип информационных множеств обычно используется, если требуется поддер- живать только словарные операции (добавление, поиск и удаление элемента), и по- зволяет осуществлять их весьма эффективно, за константное время. Второй тип структурированных информационных множеств связан с наличием отношения ли- нейной упорядоченности ключей, и этот тип порождает такие рассмотренные в дан- ной главе структуры, как поисковые деревья и кучи. 6.1. Одномерные структуры данных Деревья сортировки и кучи позволяют выполнять наряду со словарными операциями (поиска, вставки и удаления элемента), операции взятия текущего минимального и максимального элемента, а также предыдущего и следующего элемента по отноше- нию к заданному. Таким образом, указанные структуры могут использоваться и как словари, и как очереди с приоритетом. Время выполнения основных операций над деревом пропорционально высоте дерева. Если бинарное дерево "плотно заполнено" (все его уровни имеют максимальное чис- ло вершин), то его высота пропорциональна логарифму числа его вершин п. Напро- тив, если дерево является левосторонним (или правосторонним), это время возраста- ет до О(«). Высота случайного двоичного дерева (при естественных ограничениях) составляет O(log и), но те бинарные деревья, которые возникают при представлении реальных информационных множеств, могут быть далеки от случайных. Однако, приняв спе- циальные меры по балансировке деревьев, можно гарантировать, что высота дерева с п вершинами будет O(log и), причем, временная сложность поддержания балансиров- ки не выходит за рамки временной сложности основных операций. Биномиальные и фибоначчиевы кучи выполняют каждую операцию, считающуюся основной для деревьев сортировки, за время O(log п), где и — число элементов в куче (или в двух сливаемых кучах). Их преимущество состоит в возможности быстрого слияния двух куч: для двоичных куч эта операция требует 6(и) времени, а для фибо- наччиевых куч учетная (а также фактическая) стоимость операции слияния равна 0(1). Для простоты изложения будем рассматривать в качестве элементов информацион- ного множества слова. 6.1.1. Деревья сортировки Обозначим через IV = {lVt,..., IF,,} множество слов с введенным на нем отношением порядка, например, лексикографическим. Бинарным деревом сортировки или просто деревом сортировки над множеством слов IV называется бинарное «-вершинное дерево Тт каждой вершине которого со-
Глава 6. Информационные деревья 453 поставлено слово из множества W, причем для каждой вершины х выполнено усло- вие: все слова левого поддерева Т^х) предшествуют слову, сопоставленному вершине х, а все слова правого поддерева Г/х) следуют за словом в вершине х. На рис. 6.1 показаны три дерева сортировки над множеством слов {А, В, С, D} с кор- нями, помеченными словами D, В и С соответственно. Рис. 6.1. Дерево сортировки Будем называть в дальнейшем слово И7, сопоставленное вершине х, значением вер- шины х и обозначать lV(x). Построение дерева сортировки Как видно из представленного на рис. 6.1 дерева сортировки, его конфигурация су- щественно зависит от того, какое слово является значением корня дерева. Опишем алгоритм построения дерева сортировки в предположении, что корню сопоставляется слово fFi, далее происходит одновременное наращивание дерева и сопоставление слов jy2, W„ в порядке их вхождения в множество W вершинам дерева Очевидно, что построение дерева начинается с создания вершины v0— корня дерева; после со- поставления ему слова Wt создаются две вершины НРАВСЫН(у0) и ЛЕВСЫН(у()). Эти вершины будем называть свободными в отличие от корня, которому присвоено значение. Для удобства будем считать, что у свободных вершин х значение И^х) рав- но Q. функПОСТРОЕНИЕ-ДЕРЕВА(8: список) = 1 В качестве Т взять тривиальное дерево, значение корня которого £2; 2. пока S ф 0 цикл 3 IVi := Э S; р = КОРЕНЬ(Т); 4. ОБХОД : пока W(p) Ф £2 цикл 5. если Wt < И/(р) то 6. р := ЛЕВСЫН(р) 7. иначе если W-i > W(p) то 8 р := ПРАВСЫН(р) 9. иначе завершить ОБХОД все все; все;
454 Часть II. Применение графов и граф-моделей 10. Значением вершины р сделать И/г, 11. Создать в Т вершины ЛЕВСЫН(р) и ПРАВСЫН(р) со значениями £1 все; 12. возврат Т все Для произвольно взятого множества слов Wдерево может расти крайне неравномерно. Можно представить себе ситуацию, когда дерево вырождается в линейный список. Поиск в дереве сортировки Поиск в дереве сортировки состоит в поиске вершины х, значение которой W(x) рав- но заданному значению W. Поиск является частью построения дерева, поэтому алго- ритм поиска в значительной мере повторяет алгоритм из предыдущего раздела. функ Г1ОИСК-В-ДЕРЕВЕ (Г: дерево; ИЛ: слово) = 1. р := КОРЕНЬ(Т); 2. ОБХОД : пока (И/(р) ф £1) v (И/(р) * ИЛ) цикл 3. если ИЛ < И/(р) то р := ЛЕВСЫН(р) 4. иначе если ИЛ > И/(р) то р := ПРАВСЫН(р) 5. иначе завершить ОБХОД 6. % поиск успешен % все все все; 7. возврат р 8. % поиск успешен тогда и только тогда, когда W(p} ф О % все 6.1.2. ДВ/7-деревья Бинарное дерево называется балансированным по высоте, или АВЛ-деревом (дере- вом Адельсона-Вельского и Ландиса), если для любой его вершины высота правого поддерева отличается от высоты левого не более чем на единицу. Трудоемкость поиска по ЛВЛ-дереву оценивается исходя из его следующего свойст- ва; максимальная высота и-вершинного ЛВЛ-дерева не превышает (3/2)logn. Это — оценка в худшем случае. В среднем имеет место оценка 1,04 log п (для больших и). Включение новой вершины (или удаление ненужной) может привести к нарушению баланса дерева, т. е. получаемое дерево уже не будет ЛВЛ-деревом. Сохранение структуры ЛДЛ-дерева требует в случае нарушения структуры выполнения восста- навливающих операций: простого и двойного вращения. Простое вращение выполняется, когда подвешивание новой вершины х происходит со стороны длинной ветви, в результате чего в вершине v0 разность высот правого и левого поддеревьев становится равной двум (рис. 6.2), при этом путь из v0 в новую вершину состоит только из левых или только из правых дуг.
Глава 6. Информационные деревья 455 Двойное вращение выполняется, когда путь из v0 (вершины, где нарушается баланс между высотами поддеревьев) в новую вершину содержит и левые, и правые ребра (рис. 6.3). Рис. 6.3. Двойное вращение Поиск и вставка новых вершин в ЛВЛ-дереве выполняются в соответствии с алго- ритмом 6.2, дополненным процедурами проверки балансов вершин и восстановления баланса [7]. 6.1.3. Балансированные по весу деревья (ВВ-деревья) Балансированные по весу деревья (ВВ-деревья) образуют класс бинарных деревьев, в которых ограничение на высоты поддеревьев заменено ограничением на число вершин в поддеревьях. Хотя эти деревья базируются на других принципах и не срав- нимы с ЛВЛ-деревьями (эти классы не пересекаются и не содержат друг друга), они обладают схожими свойствами. От ЛВЛ-деревьев они отличаются в основном тем, что содержат параметр, который может изменяться так, что компромисс между ско- ростью поиска и допустимым дисбалансом может быть выбран произвольно. Пусть Т„ = (Ti, v, Тг) — бинарное дерево с корнем v, где 7} и Тг — левое и правое би- нарные поддеревья с щ и п? вершинами соответственно, щ + nr = п- 1, щ > 0, пг > 0.
456 Часть II. Применение графов и граф-моделей Корневым балансом р(Г„) дерева (Т„ = 7}, v, 77) называется величина Для корневого баланса всегда выполняются неравенства О < р(Г„) < 1. Дерево Тп называется балансированным по весу деревом (ВВ-деревом, бинарным де- ревом с ограниченным балансом) с балансом а, 0 < а < 1/2, если оно удовлетворяет следующим свойствам: П а < р(Г„) < 1 - а; □ 7} и 77-— балансированные по весу деревья с балансом а. Класс бинарных деревьев с балансом а будем обозначать через Вб[а]. Полностью балансированные деревья Т„ на и = 2* — 1 вершинах принадлежат классу ВВ{ 1/2], в то время как деревья Фибоначчи, определяемые соотношениями Fo — пусто, F, = •, F,+, = (F, • F,+i) принадлежат ВВ[ 1 /3]. В балансах деревьев имеется пробел, а именно: для всех а в интервале 1/3 < а < 1/2 В7?[а| = FF[l/2] Оценку для средней длины поиска в Т„ дает формула: если Т„ е Z?F[a], то I7" । + log(/? + *) - 2п, 77(a) где 77(a) = - a log a - (1 - a) log(l- a). Оценку для длины поиска по худшему случаю дает оценка для высоты дерева: если Т„ е 7?7?[а], то высота дерева Т„ не больше log(n +1) -1 log(l/(l - a)) Все указанные оценки точны: они достигаются на деревьях, у которых все подде- ревья имеют корневой баланс 1/2, т. е. на полностью балансированных (2*- ^вер- шинных деревьях. Включение нового слова в ВВ-дерево Это включение происходит следующим образом. Пусть каждой вершине х дерева сопоставлено число S(x), равное числу вершин в поддереве Т(х) с корнем в верши- не х. Двигаясь по ребрам дерева, идем, как и при построении дерева сортировки, вле- во, если слово W меньше слова в вершине, и вправо — в противном случае. На каж- дом шаге поиска проверяем, нарушит ли добавление вершины баланс дерева, если
Глава 6. Информационные деревья 457 нет. то добавляем единицу к S(x) и продолжаем движение по дереву. Если же до- бавление вершины нарушает баланс, то, прежде чем двигаться дальше, проводим преобразования, аналогичные операциям вращения для Л/17-дерсвьев. Модифицируя дерево, мы можем не знать, находится ли слово IV уже в дереве. В та- ком случае возвращаемся по пройденному пути назад к корню, восстанавливая преж- ние значения величин S(x), но не проводя обратной перестройки дерева; перестрой- ка дерева не ухудшает его качества. Простое вращение. Схема преобразования и формулы для пересчета балансов в вер- шинах представлены на рис. 6.4. Нарушение баланса происходит в вершине А. Рл = Pi / Pi + (1 - Pi) Рг Рд = Р1 + (1-Р|)Р2 Рис. 6.4. Простое вращение для 86-деревьев Двойное вращение. Схема преобразования показана на рис 6.5. Нарушение баланса происходит в вершине А. Рл = Pi / Pl + (1 - Pi) Рг Рз Р«=Рг(1-Рз)/(1-Рг Рз) Pc = Pi + (1 — Pi) Рг Рз Введем следующие обозначения: Щх) — левый потомок вершины х; 7?L(x)— правый потомок вершины х; S (х) — число вершин в поддереве Т(х); FF(x) — значение вершины х; R— указатель на вершину, где может храниться новое слово IV; RP—указатель на предка вершины, на которую направлен указатель R; S— переменная со значениями L или R и SL есть либо LL, либо RL, смотря по тому, каково значение переменной S.
458 Часть II. Применение графов и граф-моделей Рис. 6.5. Двойное вращение для ВВ-деревьев Значение S вместе со значением RP позволяет выяснить, какой указатель должен быть модифицирован во время восстановления баланса дерева. проц МОДИФИКАЦИЯ (Г: дерево Wi слово) = 1. а := баланс дерева Т; R := КОРЕНЬ(Т); 2. пока ИА т W(R) цикл 3. v:= (S(LL(R))+1)/(S (R) + 2) 4 % вычисляется баланс v первой вершины на пути от корня к новой вершине после включения новой вершины для слова ИА % 5 если ИА < W(R) то 6 S := L; 7. % новая вершина включена в левое поддерево вершины R % 8 если а<у<1-ато S (R) := S (R) + 1 9. иначе если S (R) = 2 то 10 Использовать вращение без учета новой вершины 11 . иначе вычислить баланс р правого поддерева с учетом новой вершины; 12 . если 1 - р < (1 - 2<х)/( 1 - а) то 13 Применить простое вращение 14 . иначе Применить двойное вращение все все все 15 иначе % новая вершина включена в правое поддерево % 16 . если a < v < 1 - а то S (R) := S (R) + 1 17 иначе если S (R) = 2 то 18 . Использовать простое вращение без учета новой вершины 19 иначе Вычислить баланс р нового поддерева с учетом новой вершины;
Глава 6. Информационные деревья 459 20 если р < (1 - 2а)/(1 - а) то 21 . Применить простое вращение; 22 иначе Применить двойное вращение все все все все; 23 . если SL(R) * 0 то R := SL(R) 24 иначе Создать новую вершину Q := SL(R), W(Q) = Wi все все все Если цикл закончился в результате нахождения слова W в дереве, то необходимо еще раз повторить процедуру поиска в дереве слова IV и вычесть из величины S(x) каж- дой встретившейся вершины единицу. Удаление слов из ВВ-деревьев Удаление слов, или, другими словами, вершин из ВВ-дерева, происходит аналогично их включению в дерево. А именно, следуя по ребрам вниз по дереву, уменьшаем на единицу значение S(x) для каждой пройденной вершины. Если в таком случае дере- во становится несбалансированным, применяем соответствующие преобразования и движемся дальше. Когда достигнем вершины xn, которую намерены удалить, может встретиться один из трех случаев. Еслих/у— висячая вершина, то просто удаляем ее. Если х,у имеет только одного потомка, соединяем предка вершины xw ребром с по- томком вершины xw и, таким образом, удаляем вершину xN. В противном случае на- ходим последователя (предшественника) вершины xN, ставим его на место вершины заботясь о соответствующих изменениях величин S(x) и ребер. Снова, если пре- образования были сделаны, а затем выяснилось, что вершины, которую собирались удалить, нет в дереве, исправляем величины S(x), но не реконструируем дерево. 6.1.4. Выровненные деревья Под выровненными деревьями понимаются бинарные (а также другие типы деревьев, например 2-3-деревья), у которых все висячие вершины (листья) расположены на одном уровне, информация хранится только в листьях, а в остальных вершинах хра- нится вспомогательная информация, облегчающая поиск. К выровненным деревьям, кроме упомянутых 2-3-деревьев, относятся: Н-деревья, или деревья соседства, НВ- деревья, или братские, HS-деревья (расширение класса /ТВ-деревьев), 1-2-братские деревья, бинарные деревья малой высоты, или к-деревья, RB-деревья, или правые братские деревья, и др. Бинарное дерево называется Н-деревом (деревом соседства), если все висячие вер- шины находятся на одном уровне и каждая вершина с единственным потомком имеет правого соседа с двумя потомками. Пример //-дерева приведен на рис. 6.6.
460 Часть II. Применение графов и граф-моделей Напомним, что вершина х называется непосредственно правым (непосредственно левым) соседом вершины у, если х и у — вершины одного и того же уровня и верши- на х появляется непосредственно справа (слева) от вершины у в графическом изо- бражении дерева, содержащего х и у в качестве своих вершин. Пусть /7-дерево имеет по крайней мере две висячие вершины. Добавление новой вершины может быть произведено лишь на самом нижнем уровне, т. е. добавлением нового листа. При этом у некоторой вершины может оказаться три потомка, восста- новление структуры //-дерева происходит с помощью процедуры, аналогичной про- цедуре ДОБАВСЫНА из описания словаря. Необходимость в восстановлении струк- туры дерева возникает и при удалении вершины, когда может появиться висячая вершина на уровне выше уровня листьев. Бинарное дерево называется НВ-деревом (деревом братства), если все висячие вер- шины находятся на одном уровне и каждая вершина с одним потомком имеет брата с двумя потомками. Напомним, что брат вершины v— это вершина с общим с v от- цом в отличие от соседней с ней вершины в определении //-дерева. Пример НВ-це- рева приведен на рис. 6.7. Сравнение //В-деревьев с //-деревьями показывает, что существуют //-деревья, не являющиеся //В-деревьями, и наоборот, существуют //В-деревья, не являющиеся //-деревьями. Бинарное дерево называется HS-деревом, если справедливы два условия: все висячие вершины находятся на одном уровне и единственный потомок любой вершины либо является листом, либо сам имеет двух потомков. Пример HS-дерева приведен на рис. 6.8. Рис. 6.8. HS-дерево Рис. 6.7. НВ-дерево
Глава 6. Информационные деревья 461 т Очевидно, что каждое //S-дерево является также //S-деревом, но обратное неверно, . е. класс //S-деревьев есть расширение класса //S-деревьев. Бинарное дерево называется к-деревом малой высоты, если: □ все висячие вершины располагаются на одном и том же уровне; □ вершина с одним потомком имеет по крайней мере одного правого соседа и пер- вые к правых соседей (или все правые соседи, если их число меньше к) этой вер- шины имеют двух потомков. Требование иметь хотя бы одного соседа гарантирует отсутствие вырожденных де- ревьев с единственной висячей вершиной. Любое /-дерево есть /'-дерево для к'<к. 1-дерево— это в точности //-дерево. На >ис. 6.9 изображены 1-дерево, 2-дерево и дерево, не являющееся /-деревом ни для акого /. Трудоемкость алгоритмов включения и исключения вершин для /-дерева пропорцио- (альна его высоте, относительно которой справедливо следующее: для каждого е > О существует такое /, что класс /-деревьев есть класс выровненных бинарных деревьев !ысоты h < (1 + е) log и + 1, где и — число листьев. 1-дерево 2-дерево Рис. 6.9. /-деревья малой высоты 6.1.5.1- 2-братские деревья Промежуточное положение между балансированными по высоте или весу и выров- ненными деревьями занимают l-2-братские деревья, которые, с одной стороны, об- ладают структурой выровненного дерева, а с другой — хранят информацию во внут- ренних вершинах — узлах, а не в листьях, причем узлы с двумя потомками содержат одно слово из множества S, а узлы с одним потомком слов не содержат Итак, бинарное дерево называется \-2-братским деревом, если: □ все висячие вершины располагаются на одном уровне; □ каждая вершина с одним сыном имеет брата с двумя сыновьями;
462 Часть II. Применение графов и граф-моделей □ элементы множества S хранятся в узлах дерева; П для каждого узла v с двумя сыновьями слова в левом поддереве узла v меньше слова в v, которое, в свою очередь, меньше слов в правом поддереве. Пример 1-2-братского дерева, представляющего множество S = {2, 3, 5, 7, 8, 10, 13}, приведен на рис. 6.10. Рис. 6.10. 1-2-братское дерево Ниже при описании операций над 1-2-братским деревом будем использовать сле- дующие обозначения: Xv — левый сын узла v; pv— правый сын узла v; crv— единст- венный сын узла v; Фу — отец узла v. Операция ПРИНАДЛЕЖИТ для отыскания элемента а в 1-2-братском дереве Т ис- пользует следующую процедуру: проц ПОИСК(ь': вершина а: элемент) = 1. если v— лист то % элемента а в дереве нет % 2. иначе если v имеет одного сына то ПОИСЩоь', а) 3. иначе если W(v) > а то ПОИСК(Ху, а) 4. иначе если W(v) = а то % найден элемент а % 5. иначе ПОИСК(ру, а) все все все все все Для осуществления добавления нового слова в дерево (операция ВКЛЮЧИТЬ) нуж- но вначале осуществить поиск этого слова в дереве; если поиск безуспешен, т. е. за- канчивается в листе, запоминаем вершину р — отца этого узла, создаем новый узел и производим реконструкцию дерева для сохранения его свойства быть 1-2-братским деревом. Реконструкция дерева производится с помощью процедуры UP(p. m, а), ко- торая вызывается в одном из следующих трех случаев: П узел р имеет двух сыновей 1="кр и г=рр, которые являются корнями 1-2-брат- ских деревьев;
Глава 6. Информационные деревья 463 □ вершина т есть либо лист, либо имеет только одного сына, который является корнем 1-2-братского дерева, и высота поддерева с корнем т равна высотам под- деревьев с корнями Тр и рр (рис. 6.11); □ либо a < W(p), если т есть лист, либо W{Tj) < a < lV(Tan,~) < lV(p) < H'(Tr), где Tf,) — множество слов в поддереве с корнем Ь, в противном случае. Рис. 6.11. Операция ВКЛЮЧИТЬ для 1 -2-братского дерева Рис. 6.12. Преобразование 1 проц UP(p, т: вершина; х: элемент) = 1. если р имеет левого брата q с двумя сыновьями 2. то % Здесь предполагается, что /, т и г не являются листьями. В противном случае следует учитывать, что ст не существует, a Ki, К? и Кз — пустые слова (рис. 6.12) % 3. Создать новую вершину т' и сделать ее сыном вершины Фр, расположенным между q и р; 4 Сделать / = Х.р единственным сыном вершины т' 5. Сделать т левым сыном вершины р; 6. Запомнить слово b из вершины Фр; 7. И/(Фр):=х все 8. если р имеет правого брата с двумя сыновьями то 9 Выполнить преобразование 2 (рис. 6.13)' 10 (7Р(Фр, т', К) 11 завершить UP все 12. если р имеет левого брата с одним сыном то 13. Выполнить преобразование 3 (рис 6.14); 14. завершить UP все;
464 Часть II. Применение графов и граф-моделей 15. если р имеет правого брата с одним сыном то 16 Выполнить преобразование 4 (рис. 6.15); 17. завершить UP все; 18. если р не имеет братьев то 19. % в этом случае р — либо корень, либо единственный сын своего отца % 20. Выполнить преобразованияе 5 (рис. 6.16); все все; проц ВКЛЮЧЕНИЕ-ЭЛЕМЕНТА(Т: дерево; а : элемент) = 1. % Дерево Т имеет по крайней мере корень и один элемент % 2. р := ОТЕЦ(ПОИСК(КОРЕНЬ(7), а))) 3. если р имеет только одного сына то 4. % в р не хранится ни один элемент % 5. Подвешивается к р второй лист; 6. И/(р) := а 7. % (см. рис. 6.13) % 8. иначе Создается новый лист m между Кр и рр; 9. UP(p, m а) все все Рис. 6.14. Преобразование 3
Глава 6. Информационные деревья 465 Рис. 6.16. Преобразование 5 Операция УДАЛИТЬ также требует восстановления структуры 1-2-братского дерева после собственно удаления вершины с элементом а, что всегда соответствует удале- нию вершины с двумя сыновьями. проц УДАЛЕНИЕ (р : вершина) = 1. % всякий раз, когда вызывается эта процедура выполняется одно из следующих трех условий: р имеет только одного сына, который является либо листом, либо корнем 1-2-братского дерева; р потеряла свое значение; для всех вершин q в дереве, кроме р и Рр (брата р, если таковой существует), если q имеет одного сына, то q имеет брата с двумя сыновьями % 2. если р имеет брата с двумя сыновьями то завершить УДАЛЕНИЕ 3. иначе если р имеет брата с одним сыном, то 4. Выполнить преобразование, показанное на рис. 6.17;
466 Часть II. Применение графов и граф-моделей 5 УДАЛЕНИЕ(Фр); % случай, когда р есть левый сын своего отца, рассматривается аналогично % все все; 6. если р не имеет братьев, то 7 если р--корень то 8. Удалить р сделав единственного сына р новым корнем; 9 завершить УДАЛЕНИЕ все; 10. если р — единственный сын своего отца Фр то 11. % В этом случае Фр имеет брата рФр с двумя сыновьями % 12 если >.рФр имеет одного сына то 13. Выполнить преобразования, показанные на рис. 6.18 14. УДАЛЕНИЕ(ФФр); % случай, когда рРФр имеет только одного сына, и все симметричные подслучаи преобразования на рис. 6.18 рассматриваются аналогично % все все; 15. если ХрФр и рРФр имеют двух сыновей то 16 % Предположим для определенности что Фр левый сын своего отца; симметричный случай рассматривается аналогичного 17. Выполнить преобразования (рис. 6.21); 18. завершить УДАЛЕНИЕ все все все; проц УДАЛЕНИЕ-ЭЛЕМЕНТА(7": дерево; а : элемент) = 1. р := ПОИСК(КОРЕНЬ(Г), а); 2 если оба сына р — листья то 3 Удалить один из листьев; 4 Удалить слово а из р; 5. УДАЛЕНИЕ (р) 6. иначе % В этом случае в силу определения 1-2-братского дерева либо рр, либо Ар является вершиной с двумя сыновьями предположим для определенности, что рр — бинарная вершина % 7. q := самая правая бинарная вершина левого поддерева со значением W(q) = у 8. если оба сына q — листья то % (рис. 6.20) % 9. И/(р) := у, И/(д) ;= Ф; 10. Удалить одного из сыновей q; 11. УДАЛЕНИЕ(д)
Глава 6. Информационные деревья 467 12. иначе % В этом случае q имеет левого сына г с двумя сыновьями — листьями и с W(r) = z и правого сына с одним листом (рис. 6.21) % 13. W(p) := у; W(q) := z; W(r) := Ф; 14. Удалить одного из сыновей вершины г, 15. УДАЛЕНИЕ(г) все все все Операции ВСТАВИТЬ, ПРИНАДЛЕЖИТ и УДАЛИТЬ могут быть реализованы для l-2-братского дерева, представляющего «-элементное 0(log(/?+ 1)). множество, с трудоемкостью Рис. 6.17. Преобразование удаления 1 Рис. 6.19. Преобразование удаления 3
468 Часть II. Применение графов и граф-моделей Рис. 6.20. Преобразование удаления 4 Рис. 6.21. Преобразование удаления 5 6.1.6.2-3-деревья 2-3-деревом называется дерево, в котором каждая невисячая вершина имеет двух или трех потомков (сыновей), а длины всех путей из корня в листьях одинаковы. На рис. 6.22 показаны два 2-3-дерева с шестью листьями. Пусть .S’— линейно упорядоченное множество, например множество целых чисел от 1 до п. Припишем эти числа листьям дерева в порядке их возрастания слева направо. В каждой невисячей вершине v— узле-— потребуется для обеспечения поиска две величины: £(v) и М(у) (L(v)— это наибольший элемент множества S в поддереве, корнем которого служит самый левый сын узла v; М(у) — это наибольший элемент в поддереве, корнем которого служит второй сын узла v (см. рис. 6.22). Значения Z.(v) и M(v), приписанные узлам, позволяют искать элемент, начиная с корня, способом, аналогичным двоичному поиску. Время обнаружения произвольного элемента про- порционально высоте дерева, т. е. (?(log п) для «-элементного множества S. В общем случае на порядок, в котором приписываются листьям элементы множества S, не налагается никаких ограничений. Тогда для отыскания листа, хранящего нуж- ный элемент, необходим вспомогательный механизм.
Глава 6. Информационные деревья 469 С этой целью рассмотрим следующие наборы операций: 1. ВСТАВИТЬ, УДАЛИТЬ, ПРИНАДЛЕЖИТ. 2. ВСТАВИТЬ, УДАЛИТЬ, МИНИМУМ. 3. ВСТАВИТЬ, УДАЛИТЬ, ОБЪЕДИНИТЬ, МИНИМУМ. 4. ВСТАВИТЬ, УДАЛИТЬ, НАЙТИ, СЦЕПИТЬ, РАСЦЕПИТЬ. Рис. 6.22. 2-3-деревья Структура данных, обеспечивающая выполнение операций из первого множества, называется словарем, из второго — очередью с приоритетами, из третьего — сли- ваемым деревом, из четвертого — сцепляемой очередью. Использование 2-3-деревьев позволяет реализовать эти структуры данных с трудоемкостью O(log п) на одну опе- рацию. Словари: реализация 2-3-деревьями Пусть элементы множества S приписаны листьям 2-3-дерева в порядке возрастания слева направо и в каждом узле определены функции Цу) и М(у), введенные в преды- дущем пункте. Чтобы определить принадлежность элемента к данному словарю (операция ПРИНАДЛЕЖИТ), организованному в виде 2-3-дерева, необходимо провести поиск в дереве по приводимому алгоритму. Алгоритм представляет собой очевидное обоб- щение процедуры ПОИСК в дереве сортировки. проц ПОИСК(г: вершина; а : элемент) = 1. % г— корень 2-3-дерева, в котором ищется элемент а % 2. если все сыновья вершины г— листья то 3. если а есть среди значений листьев гто 4. % найден лист со значением а % 5. иначе % нет в дереве элемента а % все 6. иначе Пусть s,- — /-й сын вершины г, 7 если а < L(r) то ПОИСКА,а) 8. иначе если у г два сына или а < М(г) то 9 ПОИСКА, а)
470 Часть II. Применение графов и граф-моделей 10. иначе ПОИСК($з, а) все все все все Чтобы в 2-3-дерево добавить новый элемент а (операция ВСТАВИТЬ), надо найти место для нового листа /, который будет содержать элемент а. Для этого проводится поиск элемента а в дереве. Если дерево содержит более одного элемента, то поиск а закончится в узле v, имеющем двух или трех сыновей, каждый из которых является листом. Возможны два случая: узел v имеет двух сыновей (/| и /2) и узел v имеет сы- новей (Ji, 12 и /3). В первом случае I делаем третьим сыном узла v. Лист I становится самым левым сы- ном узла v, если а < Ил(Л) (при этом полагаем Цу) = а и A/(v) = УИф)), средним сыном, если < а< (при этом полагаем М(у) = а), и наконец, самым правым сыном, если а > 1У(12) (при этом, возможно, надо будет изменить значения L и Му некоторых предков узла v). Во втором случае получаем ситуацию, в которой узел v имеет четырех сыновей. Что- бы сохранить свойство дерева быть 2-3-деревом, образуем новый узел g. Два левых сына оставим сыновьям узла v, а два правых сделаем сыновьями узла g, а сам узел g— сыном отца узла v (в используемой терминологии узел g становится братом узла v). Если отец узла v имел до подключения узла g двух сыновей, то процедура закан- чивается, в противном случае повторяем процедуру расщепления вершины с четырь- мя сыновьями. проц ДОБАВСЫНА(и : вершина; а : элемент) = 1. % v — вершина непустого 2-3-дерева Т, не содержащего элемента а % 2. Образовать новую вершину и'; 3. Сделать двух самых правых сыновей вершины v левым и правым сыновьями вершины v'; 4. если у v нет отца то 5. % v — корень дерева Т % 6. Образовать новый корень г, левым сыном которого сделать и, а правым v' 7. иначе Пусть f— отец вершины у; 8. Сделать v' сыном узла f, расположенным непосредственно справа от v; 9. если у встало четыре сына то ДОБАВСЫНА(7, а) все все все проц ВСТАВИТЬ! Г дерево; а : элемент) = 1 если Т состоит из одной вершины / с меткой b 2 то Образуем новый корень г'; 3. Образуем новую вершину v с меткой а 4. Делаем / и v сыновьями корня г', причем / будет левым сыном, если b < а, и правым — в противном случае
Глава 6. Информационные деревья 471 5. иначе f = ПОИСК(г, а); 6. если f не лист то 7. % неудачное завершение поиска % 8 Образовать новый лист / с меткой а, 9. если у f два сына с метками bi и Ьг то 10. если а < th то 11. Сделать / самым левым сыном вершины f 12. иначе если Ь-, < а < Д>2 то 13. Сделать / средним сыном вершины f 14. иначе Сделать / правым сыном вершины f все все 15. иначе Пусть у /"три сына с метками bi, b2 и Ьз, 16. если а < bi то 17. Сделать / самым левым сыном вершины f 18 иначе если Ь, < а < Ь2 то 19. Сделать / вторым слева сыном вершины f 20 если Ьг < а < Ьз то 21. Сделать I третьим слева сыном f 22. иначе Сделать / правым сыном вершины f все все все; 23. ДОБАВСЫНА/, а); 24 Скорректировать значения функций L и М на пути из листа с меткой а в корень все все все все Часть коррекции значений функций L и М может быть выполнена в процедуре ДОБАВСЫНА и в строках 9 — 22 процедуры ВСТАВИТЬ. Операция УДАЛИТЬ является обратной к операции ВСТАВИТЬ, поэтому ограни- чимся наброском алгоритма. Сначала процедурой П()ИСК(«, г), где г— корень дере- ва, находим лист / с меткой а, который нужно удалить. Возможны три следующих случая. □ Если I— корень, удаляем его. (В этом случае а был единственным элементом в дереве.) □ Если / — сын узла, имеющего трех сыновей, удаляем его с соответствующей кор- рекцией значений L и М. 3 Если/—сын узла/ имеющего двух сыновей s и /, то может быть одно из двух: • узел/— корень; удаляем / и/и делаем корнем второго сына s; • узел/— не корень; пусть g — брат узла/и пусть для определенности g — пра- вый брат (случай, когда g находится слева, рассматривается аналогично). Если
Глава 6. Информационные деревья 471 5. иначе 7 := ПОИСК(г, а); 6. если f не лист то 7. % неудачное завершение поиска % 8. Образовать новый лист / с меткой а; 9. если у f два сына с метками bi и Ь? то 10. если а < bi то 11. Сделать / самым левым сыном вершины f 12. иначе если bi < а < Ь2 то 13. Сделать / средним сыном вершины f 14 иначе Сделать / правым сыном вершины f все все 15. иначе Пусть у 7 три сына с метками b-i, Ь2 и Ьз, 16. если а < bi то 17 Сделать / самым левым сыном вершины f 18. иначе если Ьт < а < bz то 19. Сделать / вторым слева сыном вершины f 20 если Ь2 < а < Ь3 то 21. Сделать / третьим слева сыном f 22 иначе Сделать / правым сыном вершины f все все все; 23. ДОБАВСЫНА(7, а); 24 Скорректировать значения функций L и М на пути из листа с меткой а в корень все все все все Часть коррекции значений функций L и М может быть выполнена в процедуре ДОБАВСЫНА и в строках 9 — 22 процедуры ВСТАВИТЬ. Операция УДАЛИТЬ является обратной к операции ВСТАВИТЬ, поэтому ограни- чимся наброском алгоритма. Сначала процедурой ПОИСК(а, г), где г— корень дере- ва, находим лист I с меткой а, который нужно удалить. Возможны три следующих случая. □ Если I— корень, удаляем его. (В этом случае а был единственным элементом в дереве.) □ Если I— сын узла, имеющего трех сыновей, удаляем его с соответствующей кор- рекцией значений L и М. □ Если I— сын узла/ имеющего двух сыновей s и I, то может быть одно из двух: • узел f— корень; удаляем Inf и делаем корнем второго сына s; • узел f— не корень; пусть g — брат узла f и пусть для определенности g — пра- вый брат (случай, когда g находится слева, рассматривается аналогично). Если
472 Часть //, Применение графов и граф-моделей у g только два сына, делаем узел .v самым левым сыном узла g, удаляем / и ре- курсивно вызываем процедуру удаления, чтобы удалить / Если у g три сына, то самого левого сына делаем правым сыном узла/и удаляем I. После выполнения операции УДАЛИТЬ выполняется корректировка значений функ- ций L и М на пути из листа / в корень дерева. Очереди с приоритетами: реализация 2-3-деревьями В этой реализации предполагается, что элементы множества 5 приписаны листьям 2-3-дерева в порядке возрастания слева направо и в каждом узле определены функ- ции £(v) и М(у), введенные ранее. Операции ПРИНАДЛЕЖИТ и ВСТАВИТЬ реализуются так, как это было описано для 2-3-деревьев ранее в этом разделе. Операция МИНИМУМ выдает наименьший элемент в 2-3-дереве, который находится в самом левом листе; он отыскивается про- цедурой ПОИСК путем выбора в каждом узле самого левого сына. Нетрудно заметить, что для реализации очередей с приоритетом годны также и ЛВЛ-деревья. Сливаемые деревья Сливаемые деревья — это структура данных, в которой множество листьев не упоря- дочено, как это предполагалось ранее и с помощью которой можно выполнить по- следовательность операций ВСТАВИТЬ, УДАЛИТЬ, ОБЪЕДИНИТЬ и МИНИМУМ за время О(п log л). Каждый узел v этого дерева помечен значением НАИМЕНЬШИЙ^], т. е. значением наименьшего элемента, хранящегося в поддереве с корнем V. Функции L и Мв этом случае не используются. Операция ВСТАВИТЬ реализуется следующим образом. Новый элемент а вставляет- ся в дерево Т в произвольном месте, добавляя новый лист с соответствующим значе- нием, после чего вызывается, если нужно, процедура ДОБАВСЫНА, а также произ- водится корректировка значений функции НАИМЕНЬШИЙ. Предполагается, однако, что для такого дерева параллельно создается вспомогательный словарь в виде того же 2-3-дерева, листья которого содержат указатели на листья дерева Т. Словарь нуж- но корректировать всякий раз, когда выполняется операция ВСТАВИТЬ, но это тре- бует не более O(log и) шагов. Операция УДАЛИТЬ реализуется следующим образом. В тех случаях, когда требует- ся удалить наименьший элемент, необходимо воспользоваться операцией МИНИМУМ, в противном случае осуществляется поиск во вспомогательном 2-3- словаре для отыскания нужного листа. В остальном удаление листа производится так же, как и в общем случае для 2-3-деревьев. После удаления листа из Т нужно для ка- ждого его предка пересчитать значение функции НАИМЕНЬШИЙ. Новым значением для НАИМЕНЬШИЙ [v] будет наименьшее из значений НАИМЕНЬШИЙ [s] для двух или трех сыновей .у узла v. Если всегда пересчитывать снизу вверх, то индукци- ей по числу пересчетов можно показать, что каждое вычисление дает для функции НАИМЕНЬШИЙ правильный ответ. Операция МИНИМУМ находит наименьший элемент множества 5 при движении по дереву Т, начиная с корня; в процессе движения из любого внутреннего узла г проис-
Гпава 6. Информационные деревья 473 ходит переход к тому сыну узла v, который помечен наименьшим значением функ- Операция ОБЪЕДИНИТЬ сливает два множества S'; и S2, каждое представленное со- ответствующим 2-3-деревом Д и Т2, в одно множество следующим образом. Пусть высота дерева Т, равна Л, и пусть /ц > h2. Найдем на самом правом пути в Д узел v высотой Л2 и сделаем корень дерева Т2 его самым правым братом. Если у отца f узла v окажется четыре сына, то вызывается процедура ДОБАВСЫНА(/). Значения функции НАИМЕНЬШИЙ на узлах, потомки которых изменяются в процессе выполнения процедуры слияния, можно скорректировать тем же способом, что и в операции УДАЛИТЬ. функСЛИЯНИЕ (Ц, Тг дерево) = 1. % Строит наименьшей высоты дерево Г, содержащее деревья Т, и Т2 % 2. Пусть hi и h2 — высоты деревьев Л и Т2 3 если hi = h2 то Образовать новый корень г, сделав КОРЕНЬ(Е|) и КОРЕНЬ(Тг) соответственно левым и правым сыновьями вершины г 4. иначе если hi < h2 то Переименовываем деревья все; 5. ГЛУБИНА(КОРЕНЬ(7”1)) := 0; v := КОРЕНЬ^); 6 пока ГЛУБИНА (и) * М - h2 цикл 7 и := самый правый сын v; 8. ГЛУБИНА(и) := ГЛУБИНА(и) + 1 все; 9. Сделать КОРЕНЬ(Гг) сыном отца f вершины v, расположив его непосредственно справа от у; 10. если у f теперь четыре сына то ДОБАВСЫНА(Т) все Сцепляемые очереди Это структуры данных, реализованные в виде 2-3-дерева, которые поддерживают операции ВСТАВИТЬ, УДАЛИТЬ, НАЙТИ, СЦЕПИТЬ и РАСЦЕПИТЬ. Предполо- жим, что элементы множества 5 расположены в листьях 2-3-дерева в порядке возрас- тания слева направо и для каждого узла вычислены значения L(y) и М(у). Для сцепляемых очередей операции ВСТАВИТЬ, УДАЛИТЬ полностью те же самые, что и в словаре, а операция НАЙТИ совпадает с операцией ПРИНАДЛЕЖИТ. Операция СЦЕПИТЬ объединяет в одну очередь две последовательности элементов ^и^таких, что каждый элемент из St меньше каждого элемента из S2, давая на вы- ходе конкатенацию этих последовательностей, т. е. SiS2. Если S’, и S2 представлены 2-3-деревьями 7\ и Т2, то результатом операции СЦЕПИТЬ должно быть 2-3-дерево Г, листьями которого являются листья дерева Т\ и следующие за ним листья дерева Т2 в их первоначальном порядке. Это можно осуществить, используя процедуру СЛИЯНИЕ^,/у, следующим образом. Если h]>h2, то применяем процедуру СЛИЯНИЕ без изменений, в противном случае используем "зеркальный" вариант процедуры, заменив все вхождения слова "левый" на "правый", и наоборот.
474 Часть II. Применение графов и граф-моделей Операция РАСЦЕП ИТ Ь(«, S) разбивает упорядоченное множество S на две последо- вательности: 5|, элементы которой не больше а, и S2, элементы которой больше а, т. е. = {Ь | b < а, b е 5} и S2 = { b | b > а, b е 5}. Если .8’ задана в виде 2-3-дерева Т, то данная операция осуществляет деление дерева Т на два таких 2-3-дерева Т\ и Т2, что метки всех листьев в 7\ не больше а, а метки всех листьев в 7) больше а. Способ, которым можно осуществить это расцепление, следующий. Двигаясь по пути из кор- ня дерева Т в лист, где хранится элемент а, разбиваем наше дерево на поддеревья, корнями которых служат не сами узлы, лежащие на этом пути, а их сыновья (рис. 6.23). Эти деревья естественным образом разбиваются на две группы: деревья лежащие слева от пути, и деревья — справа от пути. На рис. 6.23 первую группу об- разуют поддеревья 7), Т2, Т3 и тривиальное дерево, состоящее из одной вершины vb а вторую — деревья 7\, Т5 и v2. Рис. 6.23. Реализация операции РАСЦЕПИТЬ Деревья слева от рассматриваемого пути и дерево, состоящее из одной вершины а, соединяются с помощью операции СЦЕПИТЬ. Аналогично соединяются деревья расположенные справа от пути. проц ДЕЛЕНИЕ (Г: дерево; а : элемент) = 1. % Строит по 2-3-дереву Т и элементу а дерево Ti, у которого метки листьев не больше а, и дерево Т2, у которого метки листьев больше а % 2. Найти путь в Г от корня к листу с меткой а; 3. Удалить из Т все вершины этого пути кроме листа с меткой а 4. % В данный момент дерево Т оказалось разделенным на два леса — левый, состоящий из всех деревьев, листья которых лежат слева от а, и из вершины а, и правый, состоящий из всех деревьев, листья которых лежат справа от a % 5. пока в левом лесу не более одного дерева цикл 6. Пусть 7) и Т2 — два самых правых дерева в левом лесу 7. Тз = СЛИЯНИЕ(Т1, Т2у, Тз отнести к левому лесу все: 8. пока в правом лесу более одного дерева цикл 9. Пусть И и Т2 — два самых левых дерева в правом лесу; 10. Тз := СЛИЯНИЕ(Т1. Тг); Тз отнести к правому лесу все все
Глава 6. Информационные деревья 475 С помощью сцепляемой очереди последовательность S2 можно вставить между парой элементов последовательности S) за время O(max(log| S||, log| S2D- Если S2 = bh b2, b„, S, = ah a2, am и S2 нужно вставить между элементами а, и а,+|, то нужно приме- нить операцию РАСЦЕПИТЬ(аЛ St) и разбить S', по элементу А, на две последова- тельности S{ = ah ..., а, и S" = а,+|, a,„. Затем применить операцию СЦЕПИТЬСЯ', &), результатом которой будет последовательность = at, a„ bt, b,„ и наконец, применить операцию СЦЕПИТЬ(5’3, SO, дающую нужную последовательность. 6.1.7. Кучи Двоичной кучей называют массив с определенными свойствами упорядоченности. Массив рассматривается как бинарное дерево. Каждая вершина дерева соответствует элементу массива. Если вершина имеет индекс i, то ее отец имеет индекс /72 (верши- на с индексом 1 является корнем), а ее сыновья - индексы 2/ и 27 + 1 Будем считать, что куча может не занимать всего массива. И поэтому будем хранить не только мас- сив Я и его длину длина(А), но также специальный параметр размер(А) (размер кучи), причем размерил) < длина(А). Куча состоит из элементов Я[1], ..., А[размер(А)]. Дви- жение по дереву осуществляется процедурами: функ ОТЕЦ(/)= возврат /72 все функ ЛЕВ(/)= возврат 27 все; функ ПРАВ(/)= возврат 27+1 все; а элемент Л[1] является корнем дерева. Элементы, хранящиеся в куче, должны обладать основным свойством кучи: /1[ОТЕЦ(7)] > /ф] для каждой вершины /, кроме корня, т. е. при 2 < 7 < размер(А). Отсюда следует, что значение потомка не превосходит значения предка. Таким обра- зом, наибольший элемент дерева (или поддерева) находится в корневой вершине де- рева (этого поддерева). Высотой вершины дерева называется высота поддерева с корнем в этой вершине (число ребер в самом длинном пути с началом в этой вершине вниз по дереву к лис- ту). В дереве, составляющем кучу, все уровни (кроме, быть может, последнего) за- полнены полностью. Поэтому высота этого дерева равна ©(log и), где п - число эле- ментов в куче. Время работы основных операций над кучей пропорционально высоте дерева и, следовательно, составляет O(log п). Рассмотрим основные операции над кучами. Процедура ПЕРЕСТРОИТЬ позволяет поддерживать основное свойство кучи: если массив А таков, что поддеревья с корнями ЛЕВ(7) и ПРАВ(7) обладают основным свойством кучи, то, выполнив ПЕРЕСТРОИТЬ(7), получаем такой массив А, в кото- ром поддерево с корнем / обладает основным свойством кучи. проц ПЕРЕСТРОИТЬ(Т) = 1. 1:=ЛЕВ(/);г:=ПРАВ(/); 2. если (I < размер(А))л(А[/]>А[7]) то макс := / иначе макс := / все; 3. если (г < размер(А))л(А[г]>А[макс]) то макс := г все;
476 Часть II. Применение графов и граф-моделей 4. если макс * i то Обменять А[/] и А[макс); ПЕРЕСТРОИТЬ (макс) все все Время работы процедуры ПЕРЕСТРОИТЬ составляет O(log ri), где п = размер(А). Процедура ПОСТРОЕНИЕ осуществляет по массиву А, содержащему элементы формационного множества, построение двоичной кучи: проц ПОСТРОЕНИЕ^ : массив) = 1. размер (А) := длина (А); 2. для / от \_длина(А)/2j до 1 цикл ПЕРЕСТРОИТЬ(/) все все Время работы процедуры ПОСТРОЕНИЕ составляет О(п), где и = длина(А). Рассмотрим некоторые использования двоичной кучи. Алгоритм сортировки массива А с помощью кучи весьма прост и эффективен: проц COPT-КУЧЕЙ (А : массив) = 1. ПОСТРОЕНИЕ(А); 2. для / от длина (А) до 2 цикл 3. Поменять местами А[1] и А[/]; размер(А) := размер(А) - 1; ПЕРЕСТРОИТЬ(1) Процедура сортирует за время О(п log ri) массив размера и, не используя дополни- тельной памяти. Рассмотрим реализацию очереди с приоритетами с помощью кучи. Возможны сле- дующие операции над очередью с приоритетами: П ДОБАВИТЬ((2, х) добавляет элемент х в множество Q, П МАКСИМУМ(0 выдает наибольший элемент множества Q, П ИЗВЛЕЧЬ(0 изымает из множества Q наибольший элемент. При реализации очереди в виде кучи максимальный элемент находится в корне, так что операция МАКСИМУМ требует 0(1) времени. Чтобы исключить наибольший элемент из очереди, нужно действовать так же, как и при сортировке: функ ИЗВЛЕЧЬ(О) = 1. макс := Q[1J; Q[1] := <Э[размер (Q)]; 2. размер(С» := размер^) - 1; ПЕРЕСТРОИТЬ(1); 3. возврат макс все Время работы функции ИЗВЛЕЧЬ составляет O(log ri), где и — размер (Q). Чтобы добавить элемент в очередь, его следует добавить в конец кучи Q (как лист), а затем дать ему "всплыть" до нужного места:
Глава 6. Информационные деревья 477 проц ДОБАВИТЬ(О, х) = 1. размер(СГ) := размер(СГ) +1; / := размер(А) 2 пока (/ >1) л (А[ОТЕЦ(|)] < х) цикл 3. Ар] := А[ОТЕЦ(/)]; / := ОТЕЦ(/) все; 4. А[/] := х все Время работы процедуры составляет O(log п), поскольку "подъем" нового листа за- нимает не более Oflog п) шагов. Биномиальные деревья— это бинарные деревья Во, Bt, В2, В3,определяемые по следующим правилам: Во — тривиальное дерево, а для любого к > 0 дерево Вк из двух деревьев Вк । рис. 6.24. Вии Рис. 6.24. Биномиальные деревья А. Максимальна степень вершины в биномиальном дереве с п вершинами составляет 0(log и). Биномиальная куча — это набор Н биномиальных деревьев, в котором: П каждое биномиальное дерево обладает свойством кучи, т. е. элемент каждой вер- шины дерева не меньше элемента ее отца; □ нет двух биномиальных деревьев одного размера (с одинаковой степенью корня). Первое свойство гарантирует, что корень каждого из деревьев содержит наименьший элемент среди его вершин. Из второго свойства следует, что суммарное количество вершин в биномиальной куче Н однозначно определяет размеры входящих в нее де- ревьев. В самом деле, общее число вершин, равное п, есть сумма размеров отдельных деревьев, которые суть различные степени двойки, а такое представление единствен- но (двоичная система счисления). Отсюда вытекает, что куча с п элементами состоит нз не более чем [Jog nJ +1 биномиальных деревьев. Корни биномиальных деревьев, составляющих биномиальную кучу, связываются всписок, называемый корневым списком, в порядке возрастания степеней. В куче с и вершинами степени корневых вершин образуют подмножество множества 0,1, ..., Jognj}. Ссылка на первый элемент корневого списка хранится в поле
478 Часть II. Применение графов и граф моделей голоеа(Н); если голова(Н) = NIL, где NIL — пустая ссылка, то куча пуста, вершина х в каждом биномиальном дереве кучи имеет указатели ОТЕЦ(х), (левый сын) и СЛЕД(х) (правый сын), а также поле степенъ(х), в Каждая СЫН(х) число сыновей вершины х. котором хранится Рассмотрим реализацию основных операций с биномиальными кучами. Процедура ПОСТРОИТЬ создает и возвращает объект Н, для которого голо ea[H\ = NIL (время работы ®(1)). Поиск минимального ключа осуществляет функция МИНИМУМ; в ней мы использу ем специальное значение со, которое больше всех значений ключей. функ МИНИМУМ = 1. у := NIL; х := аолова(Н); min := •» 2. пока х + NIL цикл 3. если х < min то min := х все; 4. у.- х; х = СЛЕД(х) все; возврат у все Длина корневого списка не превосходит |_log nJ +1, поэтому время работы процеду- ры МИНИМУМ есть O(log н). Объединение двух куч осуществляет операция СЛИТЬ, соединяющая две биноми- альные кучи в одну, используется в качестве подпрограммы большинством осталь- ных операций. Начнем со вспомогательной операции СКЛЕИТЬ, которая соединяет два биномиальных дерева одного размера (Дн), корнями которых являются вершины у и z, делая вершину z родителем вершины у и корнем дерева В*. проц СКЛЕИТЬ(у, z)= 1. ОТЕЦ(у) := z; СЛЕД(у)СЫН(г); СЫН(г) := у; степень(г) := степень(г) + 1 все Время работы этой процедуры — 0(1). Теперь рассмотрим операцию СЛИТЬ, которая объединяет биномиальные кучи Д и /72 (сами кучи при этом исчезают). функ СЛИТЬ(Н1, Н2) = 1. Содинить корневые списки Hi и Н2 в корневой список кучи Н так, 2. чтобы деревья в нем располагались в порядке неубывания корней, 3. и считать все деревья в Н необработанными; 4. пока Н содержит необработанные деревья цикл 5. Пусть Di — первое необработанное дерево в списке Н; 6. если следующее за D-i дерево 02 существует и их высоты совпадают 7. то заменить Di и D2 на дерево D = СКЛЕИТЬ(01, 02), считая D необработанным все все все
Гпава 6. Информационные деревья 479 Время работы процедуры есть O(log ri), где «-суммарное число вершин в кучах Н\ иН2. Добавление вершин осуществляется следующим образом: за время 0(1) создается биномиальная кучя Н', состоящая из одной вершины х, и за время O(log и) она объ- единяется с биномиальной кучей Н, состоящей из п вершин. Удаление минимальной вершины (информационного элемента с минимальным клю- чом) реализуется следующим образом Просматривается корневой список биноми- альной кучи Н и находится дерево D, корень которого минимален. Это дерево удаля- ется из корневого списка и рассыпается в набор биномиальных деревьев меньшего размера. Затем указанный набор деревьев объединяется с оставшейся частью кучи. Время работы операции составляет O(log и) Операция УМЕНЬШИТЬ работает не со всем информационным элементом, а только с его ключом. Результат применения операции УМЕНЫ11ИТЬ(//, х, к) состоит в уменьшении ключа элемента х биномиальной кучи Н до значения к (если к больше, чем текущее значение ключа, выдается сообщение об ошибке). Делается это так: сна- чала изменяется ключ у вершины х на меньший, а затем вершина х всплывает (как это было описано для двоичной кучи). Операция выполняется за время O(log и), по- скольку глубина вершины х есть <9(log ri). Операция удаления вершины х из Н сводится к двум предыдущим операциям: снача- ла применением операции УМЕНЬШИТСЯ, х, — со) происходит уменьшение ключа у вершины х до — со (специальное значение, про которое мы предполагаем, что оно меньше всех ключей), а затем операцией удаления вершины с минимальным ключом удаляем вершину х. Таким образом, операция УДАЛ ИТ Ь( Н, х) выполняется за время O(log«). Фибоначчиевы кучи поддерживают те же операции, что и биномиальные кучи, но делают это более эффективно (по порядку). Вместе с тем коэффициенты в оценках временной сложности операций для фибоначчиевых куч существенно выше, и по- этому использование фибоначчиевых куч редко оказывется целесообразным: обыч- ные двоичные кучи на практике эффективнее. Фибоначчиева куча Н— это набор множеств, каждое из которых представлено в виде так называемого фибоначчиева дерева: корни деревьев, составляющих кучи, связаны в двусторонний циклический список, называемый корневым списком, доступ к кото- рому осуществляется через поле минимум(Н), в котором хранится ссылка на наи- меньший корень в корневом списке. Помимо этого указателя дескриптор Н содержит также поле п(Н), в котором хранится количество вершин кучи. Каждое фибоначчиево дерево удовлетворяет основному свойству кучи: любая его вершина всегда не больше своих сыновей. Все сыновья любой вершины х этого дере- ва связаны в двусторонний циклический список (порядок в котором несущественен); при этом в вершине х хранятся четыре атрибута: число сыновей х, ссылка на какой- нибудь элемент из списка ее сыновей, ссылка на отца вершины х, а также логическое значение пометка(х). Смысл логического значения таков: по.метка(х) истинно, если вершина х потеряла сына после того, как она в последний раз сделалась чьим-то сыном.
480 Часть II. Применение графов и граф-моделей Рассмотрим реализацию операций над фибоначчиевыми кучами; оценки времени их работы приведены в табл. 6.1. Таблица 6.1. Время выполнения операций над кучами Процедура Двоичные кучи (в худшем случае) Биномиальные кучи (в худшем случае) Фибоначчивые кучи (учетная стоимость) СОЗДАТЬ 0(1) 0(1) ©(1) ДОБАВИТЬ ©(log и) Oflog и) 0(1) МИНИМУМ 0(1) O(log и) 0(1) ВЗЯТЬ МИНИМУМ ©(log и) ©(log и) O(log и) слить 0(и) O(log и) 0(1) УМЕНЬШИТЬ ©(log и) ©(log и) ©(1) УДАЛИТЬ ©(log и) ©(log п) O(log и) Операция ДОБАВИТЬ^//, х) создает циклический список из одной х, т. е. отдельное дерево, и это дерево (его корень х) добавляет в корневой список кучи Н. Операция МИНИМУМ(Н) выдает значение поля минимум(Н). Операция СЛИТЬ(/Д, Н2) строит объединенный циклический корневой список для объединенной кучи Н и выбирает в качестве значения поля минимум(Н) наименьшее из двух значений: минимум(Н\) и минимум^Нт). Операция ИЗВЛЕЧЬ(//) осуществляется в два этапа. На первом этапе после удаления минимального элемента Н то дерево, корнем которого он был, рассыпается в набор своих поддеревьев, которые добавляются к корневому списку Н. Второй этап — это уплотнение корневого списка И, в процессе которого происходит объединение де- ревьев с корнями одной степени. Цель уплотнений — всегда поддерживать такое состояние кучи, при котором степени ее вершин не превышают величины D(H) = Llog h(/7)J. Операция уплотнения реализуется следующим образом: проц УПЛОТНИТЬ(Н) = 1. А — массив размера D(l-f), все элементы которого равны NIL; 2. для всех w из корневого списка кучи Н цикл 3. х := w; d := степень (х); 4. пока A[d] ф NIL цикл 5. y:=A[d); 6. если х > у то обменять вершины х и у все; 7. Соединить деревья х и у в Н, для этого удалить у из корневого списка Н и включить у в список сыновей х, увеличив степень(х) и установив пометка(у) = ложь;
Глава 6. Информационные деревья 481 8 A[cfJ:=/V/L;cf:=c/+1 все; 9. A[d] := х все 10 минимум(Н) := NIL; 11 для / от / до 0(H) цикл 12 если Д[/] ф NIL то 13. Добавить А[/] в корневой список Н; 14. если (минимум(Н) = NIL) v (А[/] < минимум(Н)) то 15. минимум(Н):+ А[/] все все все все 6.1.8. В-деревья Деревья и проблема двухуровневой памяти Существует одна весьма практическая область применения деревьев, выводящая нас за пределы бинарных деревьев — это формирование и поддержание крупномасштаб- ных деревьев поиска, в которых необходимо и включение новых элементов, и удале- ние старых, но для которых либо не хватает оперативной памяти, либо она слишком дорога, чтобы использовать ее для долговременного хранения. В этом случае имеет смысл считать, что вершины дерева должны храниться во внеш- ней (вторичной) памяти, скажем, на диске. Если использовать для множества данных, включающих, например, миллион элементов, двоичное дерево, то потребуется в среднем приблизительно log (106), т. е. 20 шагов поиска. Поскольку теперь каждый шаг включает обращение к диску (в таком дереве ссылки представляют собой адреса на диске, а не в оперативной памяти), крайне желательна организация памяти, тре- бующая меньшего числа обращений. Идеальное решение этой проблемы состоит в использовании так называемых сильно ветвящихся (или /и-арных) деревьев, каждая вершина которых имеет не более т потомков, т. к. если происходит обращение к од- ному элементу во внешней памяти, то без больших дополнительных затрат можно обратиться и к целой группе элементов. Это предполагает, что дерево разбито на поддеревья, и эти поддеревья — как раз те группы, которые доступны одновременно. । выбудем называть такие поддеревья страницами. На рис. 6.25 показано разбитое на страницы двоичное дерево (каждая из страниц содержит 7 вершин). I Поскольку каждое обращение к странице требует лишь одного обращения к диску, то I зкономия на числе таких обращений может быть существенной Представим себе, I что каждая страница содержит 100 вершин (это вполне разумное число), в этом слу- I чае поиск в дереве с миллионом элементов будет в среднем требовать log100( 106) об- I ращений к страницам (т. е. всего около трех, а не 20). Конечно, если дерево растет I случайным образом, то в худшем случае может потребоваться даже и 104 обращений. 16 Зак. 202
482 Часть II. Применение графов и граф моделей Поэтому ясно, что для сильно ветвящихся деревьев схема управления их ростом. почти обязательна некоторая Рис. 6.25. Страницы двоичного дерева Сильно ветвящиеся, или m-арные деревья Выровненное дерево щим условиям: □ каждая вершина имеет не более m потомков; □ каждая вершина, кроме корня и висячих вершин, имеет не менее /л/2 потомков; □ корень, если он не является висячей вершиной, имеет не менее двух потомков. называется m-арным деревом, если оно удовлетворяет следую- Вершину v с единственным потомком ov будем называть унарной, вершину с двумя потомками бинарной. Будем называть также вершину, имеющую наибольшее воз- можное число потомков или являющуюся висячей, насыщенной; в противном случае будем говорить о ней как о ненасыщенной. Некоторое лг-арное дерево называется r-плотным, где г — натуральное число из от- резка [1 : т - 1], если выполнены следующие условия: П корень дерева по крайней мере бинарен; □ каждая ненасыщенная вершина, отличная от корня, имеет не менее г насыщенных братьев; П все висячие вершины располагаются на одном уровне. Сформулируем некоторые следствия из данного определения. А. Если вершина v есть единственный потомок своего предка — вершины xpv, тоот должна быть насыщенной. Б. Если вершина v имеет к потомков, г < к < т, то существует самое большее одна ненасыщенная вершина среди этих потомков при к < г и не менее г насыщенных по- томков при k> г + 1.
Глава 6. Информационные деревья 483 Класс ти-арных деревьев называется плотным, если он представляет собой класс r-плотных /л-арных деревьев для некоторого г. Класс 1-плотных деревьев будет так- же называться классом слабо плотных деревьев, а класс (т — 1)-плотных лг-арных деревьев — классом сильно плотных деревьев. Заметим, что существует только один класс плотных бинарных деревьев и он совпадает с классом братских деревьев, или ЯВ-деревьев (см разд. 6.1.3). Существуют два класса плотных тернарных деревьев. На рис. 6.26 показаны два тернарных дерева; первое представляет собой пример сильно плотного, а второе — слабо плотного дерева. Оба имеют по 11 висячих вершин. Рис. 6.26. Тернарные деревья В-деревья: определение и организация поиска В-деревом порядка т называется /л-арное выровненное дерево, у которого: □ каждая вершина (страница) содержит не более т слов (ключей); □ каждая страница, кроме корневой, содержит не менее т!2 ключей; □ каждая страница представляет собой висячую вершину (лист) или имеет k + 1 по- томков, где к — число ключей на этой странице; □ все вершины-листья располагаются на одном уровне; О корень имеет не менее двух потомков. Каждая страница В-дерева содержит ключи и указатели на своих потомков, для ли- стьев значениями указателей служат служебные слова NIL. Структуру вершины, со- держащей j ключей и j + 1 указателей, можно представить в виде, изображенном на рис. 6.27, где W\ < Wi < ... < Wj, а указатель pj указывает на поддерево, в котором хра- нятся слова, больше Wj и меньше Wi+t. Рис. 6.27. Структура вершины
484 Часть II. Применение графов и граф-i На рис. 6.28 представлены два В-дерева порядка пяти. Размещение ключей в вершине в возрастающем порядке слева направо предстг собой естественное развитие принципа двоичных деревьев и определяет метод ка элементов с заданными ключами. б) Рис. 6.28. В-деревья Поиск в В-дереве организуется следующим образом. Вначале в оперативную nai считывается корень дерева и в нем отыскивается требуемое слово И7; если его нет, то в оперативную память считывается вершина, на которую указывает указа’ р, такой, что И7 < И’< Wi+I. Используется указатель р0, если требуемое слово мен W\, и указатель (считаем, что в вершине хранятся j слов) — если требуемое cj больше Wf. Если значение указателя на некотором шаге поиска становится paei NIL, то поиск неудачен — слова W в дереве нет. Включение нового слова в В-дерево Включение нового слова IVв В-дерево происходит в три этапа: 1. Производится поиск слова И7; если слово уже есть в дереве, то поиск заканчивает' ся удачно и алгоритм заканчивается. В противном случае поиск заканчивается не удачей в листе L1. 2. Повое слово включается в лист 1Л с соблюдением лексико-графического порядка и добавлением еще одного указателя. Если общее число слов в вершине L1 после этого не превосходит m — 1 для дерева порядка т, то процедура включения слова заканчивается. В противном случае требуется процедура восстановления структу- ры В-дерева. 3. Если в вершине L1 стало m слов, то ее расщепляют на две вершины (рис. 6.29),а слово И],,,/?] помещают в вершину-предка <р£1. Таким образом, указатель р в вер- шине <р£1 заменяется последовательностью р\ р\ что в свою очередь может привести к расщеплению и т. д., вплоть до необходимости расщепления корня.
>. Информационные деревья 485 P0;Wr P[m/2]l Рис. 6.29. Расщепление вершины Рис. 6.31. Последовательное построение В-дерева
486 Часть II. Применение графов и граф-моделей Если нужно расщепить корень дерева, который не имеет предка, то просто создают новый корень и помещают в него единственное слово Дерево в таком случае становится выше на единицу. Данная процедура включения слов сохраняет свойства б-дерева. Пример включения слова z (рис. 6.30) в дерево б-дерево, изображенное на рис. 6.28, а. На рис. 6.31 приведен пример последовательного построения б-дерева, изображенного на рис. 6.28, б; включаемые ключи идут в таком порядке: 20; 40 10 30 15,35 7 26 18 22; 5; 42 13 46 27 8 32 38 24 45 25; Точкой с запятой отмечаются моменты появления новых страниц. Включение по- следнего ключа приводит к двум разделениям и появлению трех новых страниц. Удаление слов из 6-дерева Исключение слова из б-дерева— процесс довольно прямолинейный, хотя и услож- ненный в деталях. Выделим два случая: □ исключаемое слово находится в листе; □ исключаемое слово находится во внутренней вершине. В первом случае предпринимаем следующие шаги. Шаг 1. Удалить слово из вершины вместе со следующим за ним указателем. Если количество слов в странице остается в пределах допустимого, то алгоритм заканчи- вается. В противном случае требуется исправление структуры дерева. Шаг 2. Если в вершине остается меньше положенного слов, то слить ее со своим братом по правилу, изображенному на рис. 6.32. Рис. 6.32. Слияние братьев Если при слиянии вершин ограничение на количество слов не нарушается, то алго- ритм заканчивается. В противном случае выполняется разделение этой страницы по правилу, описанному в предыдущем шаге.
Гпава 6. Информационные деревья 487 Во втором случае предпринимаем нижеприведенные шаги. Шаг 1. Удалить слово из вершины (пусть это будет W) вместе с указателямир и р’, слив одновременно вершины, адресуемые указателями р и р', по правилу, показанно- му на рис. 6.33. Рис. 6.33. Слияние вершин Шаг 2. Слить вершины L1 и L2, адресуемые указателями рк и pk+i, оказавшиеся по- сле слияния расположенными рядом, и заменить указатели рк и рк+1 одним указателем на слитые вершины L1 и L2. Продолжить процесс слияния вершин, пока не будут слиты висячие вершины. Шаг 3. Для каждой слитой вершины, начиная с висячей, проверить выполнение ог- раничения на максимальное число содержащихся в ней слов. В случае нарушения ограничения применить операцию разделения вершин по правилу, применяемому при включении слов. Пример удаления слова U из дерева, представленного на рис. 6.28, а, приведен на рис. 6.34. На рис. 6.35 показан процесс "деградации" дерева, представленного на рис. 6.28, б, при следующем порядке удаления ключей (точки с запятой по-прежнему означают моменты перестройки дерева): 25; 45, 24, 38, 32; 8, 27, 46, 13, 42, 5; 22; 18, 26,7,35, 15. Предложенный алгоритм исключения слова не является единственно возможным; структура б-дерева позволяет варьировать стратегию при удалении слова. Например, можно рассмотреть подход, при котором при удалении слова из внутренней вершины оно заменяется наименьшим словом из поддерева, на которое указывает указатель, соответствующий удаляемому слову. Недостатком В-деревьев является слабая заполняемость их вершин словами. Увели- чить заполняемость можно с помошью перехода к деревьям, у которых каждая вер- шина, отличная от корня, имеет не менее [(2т — 1 )/3] потомков, а корень — не менее двух и не более т потомков (так называемые В’-деревья).
488 Часть II. Применение графов и граф-моделей Другой подход к увеличению заполняемости вершин основан на использовании в качестве базы при построении S-деревьев плотных /л-арных деревьев. Способ хра- нения информации в таком дереве аналогичен способу хранения ее в обычном S-дереве. Каждое r-плотное /л-арное дерево над множеством из и слов есть дерево высоты h, где h < log„,(H + 1). Недостатком таких деревьев является более сложная процедура восстановления структуры дерева при включении и удалении слов. Организация поиска слов внутри вершин В-дерева Так как порядок S-дерева и тем самым количество слов, хранимых в одной вершине, не ограничивается сверху, можно представить себе ситуацию, когда количество слое в одной вершине будет составлять несколько сотен. В таких случаях нужна органи- зация эффективного поиска слов внутри вершин. Для этого массив слов в вершине можно организовать в виде списков, списков с двойными связями или в виде балан- сированного дерева. Соответствующие S-деревья будем называть B-S-, В-L- или S-S-деревьями. Последний тип допускает обобщение на случай, когда структура данных в виде S-дерева используется одновременно несколькими пользователями. Как уже было отмечено, когда вершина в S-дереве порядка m переполняется (в ней оказывается m слов), она распадается на две, каждая из которых имеет не менее [от/2] -1 слов. В В-S-дереве с последовательным расположением слов в вершине
Глава 6. Информационные деревья 489 ?| | 15 | 18 | J 22 | 26 | J 35 | 40 | Рис. 6.35. Процесс "деградации" дерева
490 Часть II. Применение графов и граф-моделей разбиение может быть произведено с трудоемкостью О(т) обычными способами. Когда же вершина организована как балансированное дерево, процесс разделения вершины уже не так прост (если она не представлена 2-3-деревьями), как бы этого хотелось, хотя и имеет ту же трудоемкость. Это приводит к необходимости обобщить понятие В-дерева, ослабив требование относительно минимального числа слов в вершине и добившись этим облегчения разделения вершины на две. Этой цели слу- жит вводимое в следующем разделе понятие Дтп)-дерева. f (т)-дерево Пусть f: N -> /V— функция, заданная на множестве натуральных чисел, такая, что для всехт > 3 справедливо неравенство 2 <f/m) <Гт/2\. flni)-depeeoM называется страничное дерево, обладающее следующими свойствами: □ каждая вершина имеет не более т потомков; □ каждая вершина, исключая корень и висячие вершины, имеет по крайней мере fim) потомков; □ корень имеет не менее двух потомков; □ все висячие вершины располагаются на одном уровне; □ каждая вершина с j словами имеет следующий вид, показанный на рис. 6.36, где Pi — указатель на вершину-потомка (для висячей вершины р, = NIL). Как видно из этого определения, в отличие от В-дерева в /(да)-дереве минимальное число потомков у вершины может изменяться от 2 до Гт/2\ в зависимости от функ- ции fini). Если функция f такова, что f/m) = Г*и/2 |, то получаем обычное /2-дерево по- рядка т. Для монотонно возрастающей функции f класс у(/и)-деревьев ведет себя очень хорошо: минимальное число слов в вершине растет вместе с ростом парамет- ра т. Поиск, включение и удаление слов в /(от)-деревьях практически не отличаются от аналогичных алгоритмов для В-деревьев. Если при включении слова вершина стано- вится насыщенной, т. е. содержащей т слов, то она, как и в случае В-деревьев, распа- дается на две вершины с одним отличием: разбивается на вершину с s - 1 и вершину cm — sсловами, где s е [fim) : [т/2]]. Процесс удаления слова не отличается от соответствующего процесса для В-де- ревьев, исключая те шаги, где встречается нижняя граница числа слов. Изменения тривиальны.
Глава 6. Информационные деревья 491 S-дерееом (L-дереео.м) порядка т называется/(/«)-дерево, в котором все вершинные массивы слов организованы как последовательный список (список с двойными свя- зями). В S-деревьях операция ИСКАТЬ может быть осуществлена за время <9(log от), в то время как операции ВКЛЮЧИТЬ и УДАЛИТЬ требуют О(т) времени. Для £-де- ревьев операции ВКЛЮЧИТЬ и УДАЛИТЬ требуют 0(1) времени, тогда как опера- ция ИСКАТЬ — О(пг) времени В любом случае внутривершинные операции требуют 0(т) времени, т. к. прежде чем включить или удалить слово, мы применяем опера- цию ИСКАТЬ. Операции СЛИТЬ и РАСЩЕПИТЬ не содержат ничего, кроме про- стой пересылки слов из одной вершины в другую, и поэтому требуют О(т) времени и для S- и для 1-деревьев. Трудоемкость О(т) для внутривершинных операций является серьезным недостат- ком для 5- и A-деревьев. Это приводит к мысли использовать для внутренней органи- зации массива слов в вершинах деревьев (ЛВ./7-деревья, 2-3-деревья и др.), что при- водит к понятию /’-дерева. Т-дерееом порядка т называется /(от)-дерево, в котором все вершины представляют собой балансированные деревья частного типа (таким образом, различают ТАВЛ-де- ревья, Г2.3-деревья и т. д.). Очевидно, что поиск, включение и удаление слов в /’-дереве те же самые, что и для /(ш)-деревьев, за исключением того, что мы должны точно объяснить, как работают элементарные операции ИСКАТЬ, ВКЛЮЧИТЬ, УДАЛИТЬ, РАСЩЕПИТЬ и СЛИТЬ. Для операций ИСКАТЬ, ВКЛЮЧИТЬ и УДАЛИТЬ могут быть использованы стан- дартные алгоритмы для выбранного типа балансированных деревьев. Они требуют в худшем случае O(log от) времени. При выполнении операции СЛИТЬ вначале пере- сылаем слова из вершины в ее брата, смежного с ней, что требует О(от) времени, а потом производим слияние двух балансированных деревьев и включение раздели- тельного слова из вершины, являющейся предком обеих вершин, за время C>(log от). Все это дает оценку (?(/«). РАСЩЕПИТЬ — самая трудная из этих элементарных операций. Один из способов выполнения этой операции: Шаг 1. Выделить разделяющее слово IVS (медиану в случае С-/’-дерева). Это можно сделать за время О(/и). Ш а г 2. Расщепить балансированное дерево на два балансированных дерева слева и справа от Щу. Это требует O(log от) времени. Шаг 3. Скопировать одно поддерево в новую вершину за время О(от). С помощью более совершенной техники нахождение разделяющего слова можно довести до операции с трудоемкостью //(log т), полная трудоемкость операции РАСЩЕПИТЬ остается равной О(т). Основываясь на анализе элементарных операций, можно заключить, что /’-деревья лучше подходят для организации больших массивов информации, нежели S-, L- и, в частности, //-деревья.
492 Часть II. Применение графов и граф-моделей 6.1.9. Другие страничные деревья Слабые В-деревья Пусть p(v) обозначает число потомков вершины v. Пусть, далее, а и Ь — целые числа, удовлетворяющие неравенствам a > 2 и 2а - 1 < Ь. Дерево Тназывается (а, Ь)-деревом, если: □ все висячие вершины находятся на одном и том же уровне; □ для всех вершин v p(v) < 6; □ для всех вершин v, кроме корня, p(v) > а; □ для корня г справедливо р(г) > 2. Для Ь = 2а - 1 класс (а, б)-деревьев совпадает с классом S-деревьев порядка а. Для b > 2a (а, б)-деревья называются слабыми В-дерееьями. Величина [6/2] — 2 для (а, 6)- дерева называется гистерезисом. (2, 4)-деревья известны в литературе как "симмет- ричные бинарные S-деревья" и как "2-3-4-деревья". Глубина (а, Л)-дерева логарифмически зависит от числа висячих вершин. Это следует из соотношения 2 аЛ-1 < п < bh, где h — глубина (а, 6)-дерева, а п — число висячих вершин в Т(п > 2). Операции включения и удаления слов для (а, б)-дерева совершенно аналогичны со- ответствующим операциям для S-деревьев. Разница состоит лишь в операциях вос- становления структуры дерева, т. к. в отличие от S-деревьев информация в (а, />)- деревьях хранится в висячих вершинах, а во внутренних хранится только вспомога- тельная информация, подобно 2-3-деревьям. На рис. 6.37, а показано (2,4)-дерево слов {2,4,7,10,11,15,17,21}. Операция включения новой висячей вершины требует s + 1 расширений и 5 расщеплений вершин для некоторого s > 0. Это дает время ис- полнения операции 0(1 + л') (см. рис. 6.37, б). Удаление висячей вершины требует 5 + 1 сокращений и 5 слияний вершин для неко- торого S> 0 и, возможно, одной операции перераспределения потомков. Это дает время исполнения 0(1 + л). На рис. 6.38 представлено удаление висячей вершины из (2,4)-дерева. Оценим полную стоимость последовательности включений и удалений слов в (а, Ь}- дереве в предположении, что мы начинаем с пустого дерева. Пусть 6 > 2а. Рассмот- рим произвольную последовательность включений и удалений в первоначально пус- тое дерево. Пусть SP есть полное число расщепляемых вершин, F— полное число слияний вершин и SH— полное число операций перераспределения потомков. То- гда: SH < п, SP + F < п + (1 + L(« - 2) / (а - 1)J). Следовательно, полная последова- тельность включений и удалений имеет стоимость О(п). Приведем набросок доказательства этого утверждения. Пусть для вершины v, отлич- ной от корня (а, б)-дерева, баланс P*(v) определяется следующим образом: p‘(v) = -1, О, 1, если p(v)=a-l или p(v)=6+l; если p(v)=a или p(v)=A; если a+l<p(v)<+l.
Глава 6. Информационные деревья 493 Для корня г баланс р*(г) определяется аналогично: Р’0 = -1, О, 1, если р(г) = 1 или р(г) = 6 + 1; если р(г) = 2 или р(г) = Ь; если 3 < р(г) <-1. б) Рис. 6.37. Опреация включения: а — (2,4)-дерево слов, б — время исполнения операции Рис. 6.38. Удаление висячей вершины
494 Часть II. Применение графов и граф-моделей Дерево (Д v) есть частично балансированное (а, А)-дерево относительно вершины v, если: a - 1 < p(v) < b + 1; a < p (w) < b для всех w Ф r, v; 2 < r(w) < b, если v*r. Пусть ( Д v) — частично балансированное (а, Л)-дерево. Тогда баланс р’(7) дерева Т определяется как сумма балансов его вершин, т. е: Р’(П = 2>‘Од + р‘(г). v£r Справедливы следующие утверждения, из которых вытекает оценка стоимости пол- ной последовательности включений и удалений. А. Пусть Т— {a, b)-depeeo и пусть V получается из Т добавлением или удалением висячей вершины. Тогда Р*(^) > Р‘(7) — 1. Б. Пусть (Т, v) — частично балансированное относительно вершины v(a, Ь)-дерево с p(v) = b + 1. Расщепление v и расширение вершины х — предка вершины v — поро- ждает дерево Т'с Р^Т) > р*(7) + 1. В. Пусть (Т, v) — частично балансированное (а, Ь)-дерево с p(v) — а — I и v * г. Пусть, далее,у — брат v их — предок v. Тогда: □ если р(у) = а и Т'— дерево, получаемое слиянием v и у и сокращением х, то р’(П^Р‘(7); □ если р(у) > а и Г— дерево, получаемое перераспределением потомков, а именно переброской р(у) — а потомков от у к v, то Р’(7’) > р*(7). Г. Пусть Т— (а, Ь)-дерево с менее чем п висячими вершинами. Тогда О < р’(7) <(1 +1(л-1)/(я- 1)J). Рассмотрим построение слабого В-дерева, начиная с произвольного начального дере- ва. Пусть Т— произвольное (а, Л)-дерево. Предположим, что мы производим после- довательность включений и исключений вершин. Интуитивно ясно, что при таких действиях затронутыми оказываются только те вершины, которые лежат на пути из корня в то место, где надлежит подключить новую вершину, или на пути из корня в удаляемую вершину. Можно оценить число таких вершин. Очевидно, что изменя- ется баланс только этих вершин, и, следовательно, их число определяет разницу ме- жду балансами начального и конечного деревьев. Для того чтобы облегчить обсуждение данного вопроса, введем следующее условие: если из (а, А)-дерева удаляется лист, то он остается как фантом (призрак) (рис. 6.39). При описании алгоритмов восстановления балансов фантомы не учитываются. Пусть b > 2а и пусть Т — некоторое (а, Л)-дерево с п листьями. Предположим, что последовательность 5 включений и t удалений приводит к дереву Т'. Тогда Т' имеет n+s листьев, t из которых являются фантомами. Пусть рь ..., р,+,— позиции s + t но- вых листьев и фантомов в Т', pt >р2 > ..., > ps+i- Пусть, далее, SH— полное число пе-
Глава 6. Информационные деревья 495 рераспределений потомков, SP— полное число разделений вершин, F— полное чис- ло слияний вершин в реализации этой последовательности. Тогда: SH < г, 5+1 SP + F < 2( Гlog(w + s) 1+ 22 гlog(p, - p,_j +1)1 + (s + 0) i=2 Удаление 4-го листа и перерас- пределение потомков Доказательство этого утверждения существенно опирается на предположение 2а < Ь. Для обычных В-деревьев (Ь = 2а - I) это утверждение неверно. Применения слабых В-деревьев Представление списков с указателями. Пусть L— линейный список с и элемен- тами, упорядоченными в порядке возрастания, и пусть Т — {а, А)-дерево с и листья- ми. Говорят, что Т представляет L, если: П элементы из L хранятся в п листьях дерева Т в порядке возрастания слева направо; □ в каждой внутренней вершине v дерева Т хранится p(v) — 1 ключей; г-й ключ в v есть наибольший ключ в /-м поддереве вершины v. Пример такого дерева представлен на рис. 6.37. Указатели в списке L могут быть использованы для обозначения областей наиболь- шей активности в L. (а, 6)-деревья, как они были определены ранее, не обеспечивают эффективного поиска вблизи указателей. Это приводит к тому, что соседние элемен- ты оказываются связанными очень длинными путями. Поэтому имеет смысл ввести связанные по уровням (а, 7>)-деревья.
496 Часть II. Применение графов и граф-моделей В связанном по уровням (а, 6)-дереве, или. короче, связанном (сг, А)-дереве, все дре- весные дуги делаются проходимыми в обоих направлениях (т. е. ребрами, в термино- логии теории графов), и, кроме того, каждая вершина связывается ребрами с соседя- ми по уровню. Пример связанного по уровням (2,4)-дерева для списка (2,4,7,10,11,15,17,21,22,24) представлен на рис. 6.40. Рис. 6.40. Связанное по уровням дерево Указатель в связанном (а, А)-дереве направлен на лист. Связанное (сг, Л)-дерево до- пускает очень быстрый поиск в окрестности указателя. Относительно трудоемкости операций имеют место следующие утверждения. Пусть р — указатель в (а, /?)-дереве Т. Поиск ключа К, занимающего d-ю позицию от р, требует О( 1 + log d) времени. Включение нового листа в данную позицию в связанном (а, Ь)-дереве требует 0(1 + s) времени, где .$ есть число проведенных разбиений вершин. Удаление листа из связанного (а, 7>)-дерева требует 0(1 + _/) времени, где f— число произведенных слияний вершин. Операция объединения множеств. Связанные (а, Л)-деревья эффективны для реа- лизации следующей операции объединения множеств: для упорядоченных множеств А и В организовать множество С = Au В — {некоторые элементы из А о, В} Сильные В-деревья Сильным (w, v)-depeeoM для 2 < u < [v/2] называется /;?-арное дерево, в котором: □ все листья находятся на одном уровне; □ каждая внутренняя вершина, отличная от корня, имеет m потомков, где u<m< v; □ корень имеет т' потомков, где min(2, | Т | ) < т' < v (здесь 17 | есть число листьев в Г). Величина г = v + 1 - 2и называется устойчивостью, а величина р = (Гv/21 - и) — гис- терезисом (и, г)-дерева.
Гпава 6. Информационные деревья 497 Сильным В-деревом называется (и, у)-дерево с v > 2w. Из этого определения непосредственно вытекает, что высота A(w, v)-дерева Т есть O(log IT’D, т. к. для й>|7] имеет не меньше 2и 1,-1 и не больше vh вершин. Алгоритмы для работы с сильными В-деревьями практически те же, что и для работы с обычными В-деревьями, но для них существует больше вариантов проведения пре- образований, восстанавливающих баланс. Алгоритмы для (и, г)-деревьев характеризуются четырьмя параметрами. Порог слия- ния t, 0 < t <v -2u + 1, определяет, должно ли проводиться слияние вершин или их разделение при недогрузке. Ситуация недогрузки выбирает, какого из братьев вер- шины следует использовать при возникновении недогрузки. Стратегия расщепления вершины определяет способ разделения потомков между результирующими верши- нами. Стратегия включения возможна в двух вариантах: стратегия Z, для s > 1 преду- сматривает передачу 5 потомков недогруженной вершине, а стратегия Zo— как мож- но более равномерное распределение потомков между результирующими вершинами. Пусть Alg(/) обозначает класс всех алгоритмов для данного множества (w, у)-деревьев с порогом слияния /. A ig(7, Z,), i > 0 есть класс алгоритмов с использованием страте- гии Z,. Alg(/, s,„in) есть класс алгоритмов с порогом слияния t и гистерезисом переме- щения smin. Значение х„,п, определяется для любой стратегии включения в {щ у)- деревья, как минимум, по всем операциям включения величины min (х, у) - и + 1, где хи_у — два множества потомков, созданных при включении. Таким образом, {min(s,z+2-s) для стратегии Z,.. l+[z/2j для стратегии Zo. Пусть В{к} = В (к, Т, S) есть полное число восстанавливающих баланс операций, ко- торые необходимы при первых к операциях обновления данных в дереве (включение новых или удаление старых) в последовательности из S' таких операций для началь- ного дерева Т. Имеют место следующие утверждения. Пусть р = fv/21 - w > 1 есть гистерезис (и, v)-дерева. Тогда В(Л) > к/р + О (\Т |) для лю- бого алгоритма (и, у)-дерева из множества алгоритмов Alg(Z, smin) с начальным дере- вом Тс у > 2и + 1, t > ГЗр/21 - 1 и 5min > Гр/2~\. Для любого алгоритма из множества алгоритмов Alg(O) для (ы, у)-дерева с v > 2и име- ет место неравенство В(к) > 2>к/2 + О(]Т |). Пусть у > 2и - 1, р = Гу/21 - и и I < ГЗр/2"| - 1 или 5,ni„ < Гр/21 Пусть далее, w = min(2(/+ 1)/3, 2smjn). Тогда для алгоритмов из Alg(r, smin) для (и, у)-дерева имеет место оценка В(К) < K/w + О(\Т |). Для взвешенных операций по восстановлению баланса В(К) определяется как сумма стоимостей операций. Пусть расщепление, слияние и перераспределение потомков имеют стоимости сь с2 и с3 соответственно. Рассмотрим класс (к, у)-деревьев с гистерезисом р < [v/w] и алго-
498 Часть II. Применение графов и граф-моделей ритм из Alg(/, 5n„n). Пусть с'= (с} + с2)/2, d = 1 + с3/2с'и w = min((/+l)/J, 2c'smJc3). Тогда: В(А) < с'к!р + 0(|Т |), если t >Гф! - 1 и > [с3р/2с В(к) <с — k/w + 0(|7"|), если t <Гdp\- 1 или t = р и v четно. Для уменьшения блокирования при мультипроцессорной обработке, а также при ис- пользовании деревьев в многомерных применениях, где стоимость операций восста- новления баланса растет экспоненциально с высотой дерева, важно знать распреде- ление таких операций по уровням дерева. Следующее утверждение показывает, что количество их в (и, г)-дереве убывает экспоненциально с высотой дерева. Пусть Bh(k) — число операций восстановления баланса, которые должны быть про- ведены на уровне h при к обновлениях, примененных к пустому начальному дереву. Для класса (и, г)-деревьев с устойчивостью r = v — 2и+ 1 и гистерезисом р = [г/2] и алгоритмов из Alg(/, smin) имеем: В\к) < к/{р + 1/, если t > |Зр/2| и лп1Н| > 1 + [р/2]; Bh(Jc) < к (3/5)Л-1 в (2,4)-деревьях с t = 0; //"(А) < к!(г + I)*"1, если t = 0 и и > [(v + 3)/4]. Сильные ©"-деревья Пусть BSTAR— стандартный алгоритм построения В’-дерева [3], который работает со структурой данных в виде (и, г)-дерева, где и = 2/ + 1 и v = 3/ + 1. При применении алгоритма BSTAR к начальному (и, г)-дереву Т имеют место оценки: В(К) > О(к log(| Г |) — в худшем случае, если 3(w - 1) = 2(v - 1); В(к) <2к+ О(|Т |), если 3(w - 1) < 2(v - 1). 6.2. Многомерные структуры данных Пусть имеется множество информационных элементов, характеризующихся набора- ми из А: ключей Ко, ..., Kk-i. Каждый такой информационный элемент может рассмат- риваться как запись, состоящая из к полей, или как точка в A-мерном пространстве. Многомерные деревья предназначены для организации словарей для таких множеств. 6.2.1. Многомерное дерево сортировки Бинарное дерево называется многомерным деревом сортировки или k-d-деревом сортировки, если: □ каждой вершине v сопоставлен дискриминатор DISC(v) так, что дискриминатор корня равен нулю, дискриминаторы его сыновей равны единице и, вообще, дис- криминатор вершины на уровне / равен /(mod А); □ для каждой вершины v с дискриминатором j выполнено условие: левый потомок Xv имеет у-й ключ Kficv) меньше /-го ключа К}(у) в вершине v, а правый пото-
Глава 6. Информационные деревья 499 мок pv имеет у-й ключ Kj{pv) больше у-го ключа в вершине v, т. е. Kflw) < Kj(v) < <К^ру). В случае равенства ключей можно поступать по-разному, но для большинства при- ложений полезным оказывается следующий прием. Определим для вершины v у-й суперключ Wj(v), положив ВД = tyy)KJ+i(y) ... Kk4(y)K0(v)K}(y)... К^(у), т. е. приняв в качестве суперключа циклическую конкатенацию ключей, начинаю- щуюся с ключа К, Тогда условие второе в определении многомерного дерева сорти- ровки заменяется следующем условием: П для каждой вершины v с дискриминатором j выполнено условие: левый потомок имеету-й суперключ меньшеу-го суперключа Wfy) в вершине v, а правый потомок имеету-й суперключ большеу-го суперключа в вершине v. Пусть записи представляют собой точки в двумерном евклидовом пространстве (рис. 6.41), где прямоугольники изображают размер поддеревьев. Соответствующее 2</-дерево показано на рис. 6.42. Рис. 6.41. Множество точек на плоскости Включение новой записи k-d-дерево Включение новой вершины в A-J-дерево принципиально не отличается от анало- гичной процедуры, определенной для дерева сортировки. Построение дерева также начинается с создания вершины г — корня дерева; после сопоставления ему записи
500 Часть II. Применение графов и граф-моделей Рис. 6.42. Многомерное дерево сортировки для множества точек W(r) создаются две свободные вершины: ПРАВСЫН(г) и ЛЕВСЫН(г), значение ко- торых равно 0. Для включения новой записи в /с-с/-дерево производится поиск, если записи в дереве нет, то поиск заканчивается в листе L, значение которого равно 0. Сопоставляем вносимую запись данному листу и превращаем его во внутреннюю вершину подвешиванием к нему двух листьев. проц ВКЛЮЧЕНИЕМ: дерево; W: запись) = 1. % Процедура в R-d-дерево Т включает запись М= (Ко, Ki, .... Км) % 2. р := корень дерева Т; j := DISC(p); 3. пока И/(р) 0 цикл 4. если И/(р) = Мто завершить ВКЛЮЧЕНИЕ % запись Месть в дереве Г % 5. иначе если W < М/р) то 6. р := ЛЕВСЫН(р); % М) = (К;, Куц, ..., Км, Ко. .... Кн) % 7. иначе р := ПРАВСЫН(р) все все; 8. М(р) := М DlSC(p) := (DlSC(p) + 1) mod R; 9. Создать вершины ЛЕВСЫН(р) и ПРАВСЫН(р); 10. М(ЛЕВСЫН(р)) := М(ПРАВСЫН(р)) := 0; все все Нетрудно проверить, что 2-с?-дерево (см. рис. 6.42) может быть получено последова- тельной вставкой записей в порядке А, В, С, D, Е. F, G. Поиск в kd-дереве Поиск состоит в нахождении множества записей, удовлетворяющих данному запро- су. Запрос может иметь различный вид, от простого, например {Р | Кз(Л) = 7}, до сложного, например {Р | (1 < К2(Р) < 5) & (2 < К5{Р) < 4)} v (Ki(P) = 8)}. Рассмотрим
Глава 6. Информационные деревья 501 три, все более усложняющихся типа запросов, каждый из которых есть обобщение предыдущего. Точный поиск записи. Это простейший вид запроса, он состоит в проверке, находится ли запись IV- (Ко, К\,Кк-\) в дереве. Обработка этого запроса ничем не отличается от реализации операции ПРИНАДЛЕЖАТЬ. Если этот тип запроса— единственный допускаемый, то использование A-J-дерева в качестве структуры данных ничем не оправдывается, достаточно обойтись каким-либо типом дерева сортировки из преды- дущего раздела, рассматривая суперключ W^KD,K{, ...,Kk^ в качестве единственного ключа. Поиск по множеству ключей. При этом виде запроса задаются набор ключей и их значения и требуется найти множество записей, у которых специфицированные клю- чи принимают указанные значения. Пусть {л;} и {v,} — такие множества, что специ- фицированные ключи суть Ks,KSi, а значения, которые они должны иметь, суть vx,..., vs. Тогда искомым множеством записей будет {Р | KS(P) = v„, 1 < i< t}. Идея поиска состоит в следующем. Пусть на некотором шаге алгоритма мы попали в вершину Р. Если 1Г(Р) удовлетворяет запросу, то Р заносится в множество-ответ. В противном случае допустим, что дискриминатор вершины Р равен j. Тогда воз- можны два случая: j = s, для некоторого i, 1 < i < t и j {.v,}. В первом случае продол- жаем поиск в левом поддереве вершины Р, если vsi < К,(Р), и в правом, если vf/ > К(Р). (Если имеет место равенство у„ = К^Р), то переход к правому или левому поддереву определяется принятыми соглашениями.) Если j g {sj, то мы должны продолжить поиск в обоих поддеревьях. При этом предполагается, что поддеревья не пусты. Поиск в ограниченной области. Более общий тип запроса — поиск в ограниченной области— предполагает задание границ изменения значений специфицированных запросом ключей. При этом не требуется знать определение области, в которой ведется поиск, достаточно знать значения (или уметь вычислять) двух функций: В-ОБЛАСТИ и ПЕРЕСЕЧЕНИЕ-ГР АНИЦЫ-ОБЛАСТИ. Первая указывает для каж- дой рассматриваемой в данный момент вершины, находится ли она в области или нет, вторая оценивает значение ключей и отмечает выход за пределы области. Поиск ближайшего соседа. Несколько особняком стоит запрос следующего вида. Для данной функции расстояния D семейства точек В в Л-мерном пространстве и точки Р (в том же пространстве) необходимо найти в В ближайшего соседа точки Р. Ближай- ший сосед — это такая точка Q, что (V7? е B)(R *Q)=> (D(R, Р)<> D(Q, Р)). Аналогичный запрос можно сформулировать и для нахождения т ближайших сосе- дей вершины Р Алгоритм поиска в области Данный алгоритм также решает задачу поиска по множеству ключей. Сделаем пред- варительно одно замечание. Ключи всех вершин в поддереве любой вершины, ска-
502 Часть II. Применение графов и граф-моделей жем Р, ограничены рамками, определяемыми позицией Р в A-J-дереве. Например, если Р находится в правом поддереве любой вершины Q и дискриминант Q равен у, то все вершины в этом поддереве, включая Р, у-больше Q, т. е. если R в этом поддере- ве, то K/R) > K,{Q), и если к тому же R лежит в правом поддереве вершины Р, то Kj(R) > Kj{P). Чтобы учесть эти сведения в алгоритме поиска, определим граничный массив для хранения такой информации. Если В— граничный массив, сопоставлен- ный вершине Р, то В имеет 2k элементов В(0),..., В(2к — 1), причем если Q— потомок Р, то для всех целых j е [0 : к - 1] справедливо неравенство В(2у) < Kt(Q) < B(2J + 1). Граничный массив считается заданным, если вначале для всех j е [0 : к — 1] В(2у) = = - оо и B(2j + 1) = + оо. Например, граничный массив для вершины С (см. рис. 6.25) есть (50, 100, 0, 100). Это означает, что значения ключа Ко в этом поддереве заключе- ны между 50 и 100, а все значения ключа Kt — между 0 и 100. Алгоритм 6.1. Поиск в области Дано. А-с/-дерево Т, область поиска в виде гиперпрямоугольника, определяемого гра- ничным массивом RECDEF. Требуется. Множество вершины дерева из этой области. Метод. функ В-ОБЛАСТИ(р: вершина) = 1. % вырабатывает истинное значение, если р принадлежит специфицированной области % 2. для / от 1 до к - 1 цикл 3. если Ki(p) < RECDEF(2/) то возврат ложь все; 4. если Ki(p) > RECDEF(2/ + 1) то возврат ложь все все; 5. возврат истина все; функ ПЕРЕСЕЧЕНИЕ-ГРАНИЦЫ-ОБЛАСТИ(В : массив) = 1. % выдает истинное значение, если гиперпрямоугольник, определяемый массивом В, пересекает гиперпрямоугольник, определяемый массивом RECDEF % 2. для I от 0 до 2(к - 1) через 2 цикл 3. если B[l] > RECDEF (/ + 1) то возврат ложь все; 4. если Ь[1 + 1] < RECDEF(/) то возврат ложь все все; 5. возврат истина все; проц НАЙТИ(р : вершина) = 1. % процедура сообщает, что р лежит в специфицированной области; вид сообщения определяется реализацией % все; начало 1. р := КОРЕНЬ (7); 2. если В-ОБЛАСТИ (р) то НАЙТИ(р) все;
Глава 6. Информационные деревья 503 3. % Создать граничные массивы Bl и Вн и скопировать В в оба массива; BL —для ЛЕВСЫН(р), Вн — для ПРАВСЫН(р) % 4 j := DISC(p); Bl(2 j + 1) := К/p); Вн(2-У) = Kfip); 5. % Производится модификация граничных массивов, исходя из того факта, что ключ К/p) является верхней границей для ключей К, в вершинах из левого поддерева вершины р и нижней границей для ключей Kt в вершинах из правого поддерева вершины р % 6 если (ЛЕВПОДДЕРЕВО(р) * 0) л ПЕРЕСЕЧЕНИЕ-ГРАНИЦЫ-ОБЛАСТИ(В£) 7 то ПОИСК-В-ОБЛАСТИ(ЛЕВСЫН(р), Bl) все; 8. если (ПРАВПОДДЕРЕВО(р) * 0) л ПЕРЕСЕЧЕНИЕ-ГРАНИЦЫ-ОБЛАСТИ(Вн) 9. то ПОИСК-В-ОБЛАСТИ(ПРАВСЫН (р), Вн) все конец Аналогичные процедуры могут быть написаны для других по форме областей с при- менением логических функций И, ИЛИ, НЕ. Удаление вершины из /г-д-дерева Удаление вершины будем рассматривать как удаление корня некоторого поддерева. Если Р не имеет поддеревьев, то просто удаляем Р. Если Р имеет потомков, то он может быть заменен одним из них, скажем Q, который сохранит порядок, индуциро- ванный вершиной Р. Иными словами, все вершины из правого поддерева вершины Р должны быть в правом поддереве вершины Q и то же самое должно быть относи- тельно левого поддерева. Предположим, что дискриминатор вершины Р равен j. То- гда Q должен быть /-максимальным элементом (вершиной, в которой ключ К, имеет наибольшее значение среди всех вершин поддерева) в левом поддереве вершины Р (или /-минимальным в правом поддереве вершины Р). Когда Q найдена, она может служить новым корнем вместо Р, нужно только провести необходимую реорганиза- цию дерева для удаления Q из прежней позиции в дереве. Алгоритм 6.2. Удаление вершины Дано, к-d-дерево Т, вершина Р. Требуется. Модифицированное А-с/-дерево без вершины Р. Метод. процУДАЛЕНИЕ(Р: вершина) = 1. если (ЛЕВПОДЦЕРЕВО(Р) = 0) л (ПРАВПОДДЕРЕВО(Р) = 0) то 2 Удалить Р из дерева; завершить УДАЛЕНИЕ 3 иначе J := DISC(P); 4. если ПРАВПОДДЕРЕВО(Р) * 0 то 5. Q := (-минимальная вершина в ПРАВПОДДЕРЕВО(р) 6 % Здесь используется алгоритм поиска в области с соответствующими уточнениями % 7 QF := отец вершины Q;
504 Часть II. Применение графов и граф-моделей 8. QS := ЛЕВСЫН или ПРАВСЫН, смотря по тому, левый или правый сын вершина Q у своего отца 9. иначе Q := /-максимальная вершина в ЛЕВПОДДЕРЕВО(Р) 10. QF := отец вершины Q; 11. QS := ЛЕВСЫН или ПРАВСЫН, смотря по тому, левый или правый сын вершина Q у своего отца все; 12. УДАЛЕНИЕ(<Э5(С|А)); % Этот рекурсивный вызов делает вершину Q свободной, так что она может становиться новым корнем взамен Р % 13. DISC(Q) :=/; ЛЕВПОДДЕРЕВО(О) := ЛЕВПОДЦЕРЕВО(Р); 14. ПРАВПОДДЕРЕВО(О) := ПРАВПОДДЕРЕВО(Р) все все Условный оператор в строке 5 является источником многих неприятностей, т. к. при последовательном удалении вершин из дерева он все время заставляет удалять вер- шины из правого поддерева. Это продолжается до тех пор, пока не будет исчерпано все дерево, что приводит к резко деформированному дереву. Чтобы избежать этого, используются различные стратегии. Например, выбирают вершину из большего по размеру поддерева, поочередно из правого и левого поддеревьев, выбирают дерево с помощью датчиков случайных чисел. Оптимизированные k-d-деревья В некоторых применениях использовать Л-J-деревья, получаемые последовательным включением слов, подаваемых на вход алгоритма в произвольном порядке, достаточ- но невыгодно из-за возникающей конфигурации дерева (возможно, неудачной). К ним относятся случаи, когда нужно выполнить большое количество поисковых операций при малом количестве включений и исключений, а также когда известно, в каком порядке будут встречаться вершины. К счастью, возможно, хотя это отразит- ся на времени обработки дерева, так оптимизировать А-г/-дерево, что все листья будут располагаться на двух смежных уровнях. Приводимая процедура ПОСТРОЕНИЕ строит А-гАдерево таким образом, что число вершин в правом поддереве каждой вершины будет отличаться от числа вершин в левом поддереве не более чем на единицу. Чтобы построить оптимизированное А-гАдерево, используется процедура ОПТИМИЗАЦИЯ-ДЕРЕВА с параметрами А и у, где А — множество записей, заданное, например, в виде связанного списка, и j = {0, 1,..., к- 1} — множество значений дискриминатора. проц ОПТИМИЗАЦИЯ-ДЕРЕВА(А : множество;/ : целое; v: вершина) = 1. если А * 0 то 2. Р /-медиана множества А; % это элемент множества А, специфицированный ключом Kj, с номером [| А | / 2] или [| А | / 2 + 1] % 3. Al - {а е А; а /-меньше Р}; Ан := {а е А; а /-больше Р};
Гпава 6. Информационные деревья 505 % Al и Ан — семейства вершин, из которых конструируются левое и правое поддеревья соответственно; их мощность различается не более чем на единицу % 4. W(v) := Р\ DISC(v) :=/; М := (/ + 1) mod к; 5. ОПТИМИЗАЦИЯ-ДЕРЕВА(А, М, ЛЕВСЫН(у)); 6. ОПТИМИЗАЦИЯ-ДЕРЕВА(Ан, М, ПРАВСЫН(у)) все все; проц ПОСТРОЕНИЕ^ : множество) = 1. В качестве Т взять одновершинное дерево, значение корня которого равно О 2. v := КОРЕНЬ(Т); ОПТИМИЗАЦИЯ-ДЕРЕВА(А, 0, v) все Свойства fc-d-деревьев Достоинство A-J-деревьев состоит в возможности их использования для обработки различных типов запросов, а также в небольшой трудоемкости алгоритмов для них. Так, включение новой вершины в ,7-вершинное дерево имеет в среднем трудоем- кость, равную O(log и). Поиск по множеству ключей может быть организован с тру- доемкостью О(/7(*-|)/а), где t— число специфицированных в запросе ключей. Удале- ние корневой вершины имеет трудоемкость О(л<А-|)Л), а удаление произвольной вер- шины — O(log и). Трудоемкость построения оптимизированного дерева составляет Оф log и), при этом оптимизированное дерево гарантирует логарифмическую трудо- емкость поиска. 6.2.2. Многомерные В-деревья Определение многомерного В-дерева Пусть D есть база данных, в которой все записи снабжены и различными атрибутами. Каждая запись в D может рассматриваться как упорядоченный набор (АГ,, К2,..., К„) значений, которые соответствуют атрибутам А,, А2,..., А„. Пусть Vj,J =1,2,..., и, есть число различных значений атрибута At (ранг атрибута А,). Организация базы данных предусматривает, кроме О, еще справочник, содержащий значения, которые должны быть присвоены атрибутам, и их ассоциативные указате- ли. Будем предполагать, что и О, и справочник находятся на внешних запоминающих устройствах и что страница есть единица пересылаемой информации между внешней и оперативной памятью. Числа доступа суть указатели в справочнике, которые фик- сируют размещение записей в соответствующих страницах данных. Каждый из и атрибутов /17, который должен быть индексирован, представляется в нашем дереве-справочнике отдельным уровнем (см. разд. 6.2.1). Однако каждая вершина в нашем дереве сама изображает сложную структуру, а именно В-дерево. Основная структура многомерного В-дерева, или, короче, MDBT, представлена на рис. 6.43, где вершины, изображаемые треугольниками, суть В-деревья, необязатель- но одного и того же порядка и размера. Более формально, значения атрибута (ключа)
506 Часть II. Применение графов и граф-моделей А, организованы в виде В-дерева порядка wi„ где каждая вершина содержит (т,— 1) значений атрибута и (2т, — 1) указателей. Структура вершины в В-дереве для Л, имеет вид, изображенный на рис. 6.44. Уровень 1 Рис. 6.43. Многомерное В-дерево Рис. 6.44. Структура вершины в В-дереве Здесь Kj — J-e значение атрибута Af, Р} указывает на вершину на следующем уровне того же самого В-дерева, содержащую значения атрибута А, в интервале между К, и KJ+ й Fj указывает на В-дерево на уровне (z + 1), которое содержит множество значе- ний атрибута Ai+ ь встречающегося вместе с А/ в базе данных D. Множество значений атрибута A,+ i, которые имеют одного и того же предка на уровне /, называется сыновьим множеством (на уровне i + 1), а соответственно Fj, j = 1, 2, ..., ли/ — 1, называются указателями сыновьих множеств (на уровне /). Часть конструкции MDBT, показанной на рис. 6.43 (заключенная в прямоугольник), дета- лизируется на рис. 6.45 для иллюстрации использования типов Р и F. В-указатели изображаются сплошными линиями, в то время как Р-указатели — штриховыми. ХК0, ХКу,..., ХК$ суть некоторые значения в В-дереве X, a FXKq, FXKi, ..., FXK^ — соответ- ствующие сыновьи множества.
Гпава 6. Информационные деревья 507 Заметим, что на n-м уровне F-указатели могли бы прямо указывать на записи в базе данных D, если существует однозначное соответствие записей комбинации значений атрибутов или если база данных разбита на кластеры. Однако, т. к. кластеризация не существенна для нашего случая, предполагаем, что все F-указатели на n-м уровне представляют адреса страниц доступа, т. е. страниц, содержащих указатели, не соот- ветствующие записи данных. Более того, будем предполагать, что все числа доступа для данной комбинации значений атрибутов помещены в одну страницу. Для того чтобы позволить прямой доступ к любому уровню I дерева MDBT, все сы- новьи множества на уровне i связаны вместе, а указатель LEVEL(7) обеспечивает на- чало просмотра каждого такого связанного списка. Корневая вершина каждого В-дерева включает дополнительный указатель NEXT, который обеспечивает связь с корнем следующего в списке В-дерева. В дополнение к указателю NEXT корневая вершина каждого В-дерева содержит два других указателя: LEFT и RIGHT. Для дан- ного В-дерева X указатели LEFT и RIGHT идентифицируют соответственно самое левое и самое правое сыновьи множества на уровне i + 1 с предками, расположенны- ми в X Эти указатели изображены на рис 6.43 и 6.45, они могут быть использованы для ликвидации необязательного поиска при ответе на частичные и ранговые запро- сы (см. разд. 6.2.3), если упорядочение реализуется в сыновьих множествах. Рис. 6.45. Фрагмент многомерного В-дерева, представленного на рис. 6.44 Пусть L— связный список, чье начало задается указателем В, и пусть х и у— два элемента из списка L. Будем говорить, что х предшествует у, если элемент х ветре-
508 Часть II. Применение графов и граф-моделей чается прежде элемента у при последовательном просмотре списка L от входной точки В. Пусть А' и Y— два В-дерева на уровне I, как показано на рис. 6.43. Обозначим через {ХК0, ХКЪ ..., ХК/} и {YKq, YK\, ... YKP} подмножества значений атрибута А„ содер- жащихся в X и Y соответственно. Кроме того, FXK, и FYKj обозначают сыновьи мно- жества на уровне z+ 1, ассоциированные со значениями ХК, и YK, для z = 0, 1, ..., / и j = 0, 1, ..., р. Упорядочение, определенное на MDBT, удовлетворяет следующим условиям: П если ХК, меньше, чем XKj для tej и z, je{0, 1, ..., /}, то FXK, предшествует FXKt в связанном списке с указателем LEVEL(Z + 1); П если FXK, предшествует Z и Z предшествует FXKr i,j е {0, 1, то Z = FXK0 для некоторого t е {0, 1,..., /}. Другими словами, сыновьи множества, обозначае- мые как FXK, для z е {0, 1, ..., /}, последовательно связаны (Данные два условия справедливы также для YK, и FYKh / е {О, I, ...,р}); □ для z е {0, 1, ..., 1} и для j е {0, 1, ..., р} FXK, предшествует FYKj в связанном спи- ске с указателем LEVEL(z + 1) тогда и только тогда, когда X предшествует Y в списке с указателем LEVEL(z). Предположим, что множество значений {ХКп, ХК{, ...,ХК/} в В-дереве X упорядочи- вается следующим образом: ХК^ХК,, если i<j для I, je{0, 1, ..., /}, т. е. ХК0 и XKt являются соответственно наименьшим и наибольшим значениями в множестве. То- гда в соответствии с упорядочением сыновьи множества, обозначаемые FXK, для i е {0, 1,..., /}, последовательно связаны в список с указателем LEVEL(z + 1) и, кроме того, FXK0— самый левый среди сыновьих множеств, a FXKL — самый правый сре- ди сыновьих множеств дерева X (см. рис. 6.45). (Заметим, что страницы доступа мо- гут интерпретироваться как сыновьи множества, расположенные на уровне п+1. Следовательно, определения связывания и упорядочения применимы также к спи- скам доступа.) Стратегии поиска в дереве MDBT Здесь рассматриваются следующие типы запросов: □ на точный поиск— специфицирует значение каждого индексированного атри- бута; □ с частичным соответствием— специфицирует значения для d<n индексирован- ных атрибутов; П объемный— в нем специфицируется для каждого индексированного атрибута интервал [/,: и,] значений. Для дерева MDBT, у которого размеры всех комбинаций сыновьих множеств пред- полагаются равновероятными, временные трудоемкости обработки запросов имеют следующие значения: □ точный поиск — трудоемкость в худшем случае O(log TV); □ частичное соответствие — трудоемкость в худшем случае O(N log TVW); П объемный запрос (с и, - /, = 2 для всех I) — трудоемкость в среднем O(log N).
Глава 6. Информационные деревья 509 Обозначив через S, средний размер сыновьего множества на уровне Z, имеем № иУ= 1 = 1 1=и-с/+1 Для запроса на точный поиск, очевидно, достаточно иметь доступ только к одному В-дереву на каждом уровне для того, чтобы найти единственную страницу доступа, соответствующую данной комбинации значений. В-дерево, к которому должен быть обеспечен доступ на уровне i, определяется F-указателем, сопоставленным значению в В-дереве, в которое был осуществлен доступ на уровне (7 — 1) в соответствии с за- просом. Дерево MDBT имеет особенности, обеспечивающие эффективную стратегию поиска при обработке запроса с частичным соответствием. Во-первых, заметим, что может быть обеспечен прямой доступ на любой уровень i благодаря тому, что сыновьи множества на одном и том же уровне связаны вместе в список с указателем LEVEL(z). Во-вторых, полный перебор на уровне, соответствующем неспецифициро- ванному атрибуту, устраняется благодаря упорядочению, реализованному на сы- новьих множествах, и специальным указателям, предусмотренным для корня каждо- го дерева. Например, предположим, что атрибуты А, и A, (i < j) были специфицирова- ны запросом с частичным соответствием, в то время как атрибуты, соответствующие уровням /+1, z + 2,..., J— 1, оставались неспецифицированными. Тогда В-деревья, в которых должен осуществляться поиск на уровне j для каждого значения X, удовле- творяющего запросу на уровне i, определяются следующим образом. F-указатель, ассоциированный с X, указывает на В-дерево уровня z + 1, содержащее множество значений, которые квалифицированы в соответствии с запросом, т. к. атрибут не спе- цифицирован. Однако в нашей стратегии поиска достаточно иметь доступ только к корню В-дерева, чтобы восстановить указатели LEFT и RIGHT, которые определяют границы отрезка списка на уровне i + 2, могущего удовлетворить запрос. Более того, если j не равно i + 2, то этот весь подсписок квалифицируется как соответствующий запрос; и должен быть обеспечен только доступ к корням самого левого В-дерева и самого правого В-дерева в этом подсписке, чтобы восстановить два указателя, кото- рые определяют границы отрезка связанного списка сыновьих множеств на уровне z + З, который релевантен нашему поиску. Этот процесс продолжается аналогичным образом, пока не будет достигнут уровень /. Объемный запрос— это запрос, в котором для каждого атрибута специфицируется отрезок [£, : {/,]. Упорядочение, установленное для сыновьих множеств на данном уровне, делает достаточным осуществление поиска только для двух значений в сы- новьем множестве (В-дереве) на уровне i: /„ которое равно £, (или это есть ближай- шее значение, большее £,), и г/„ которое равно U, (или это есть ближайшее значение, меньшее £/,). Снова F-указатели, ассоциированные с /, и zz„ будут определять границы подсписка В-деревьев на уровне /+ 1, релевантных нашему процессу поиска. Таким образом, упорядочение, определенное на сыновьих множествах на каждом уровне, есть важная особенность MDBT. Включение новой записи Пусть й|, я2, ..., ап — значения, специфицированные для атрибутов At, А2, ..., А» соот- ветственно, в записи, предназначенной для включения в базу данных. Если комбина-
510 Часть II. Применение графов и граф-моделей ция «|, «2> •••> уже существует в справочнике, никаких изменений в него вносить не нужно, исключая добавление указателя доступа. С другой стороны, предположим, что комбинация at, a2 ..., a,-[ существует в справочнике (2 </<«), а а\, а2, .... д,— нет. Иначе говоря, д, не содержится в сыновьем множестве для Если F,, F2,..., Fj-y обозначают сыновьи множества для а2,..., соответственно, то а, должно быть включено в Е, _ (. (Заметим, что F, будет также использоваться для обо- значения адреса корня соответствующего В-дерева.) После включения at в F,_ t сыновье множество для а„ обозначаемое F„ содержит единственное значение «,+| и должно быть включено как одностраничное В-дерево в подходящее место внутри связного списка сыновьих множеств на уровне i + 1. Таким образом, вопрос состоит в том, как локализовать сыновье множество F*,, которое должно предшествовать В, на уровне /+1. Предположим сейчас, что а, не есть наи- меньшее значение в F,_i; этот случай мы рассмотрим позже. Тогда из имеющего ме- сто в дереве MDBT упорядочения вытекает, что F* есть сыновье множество, ассо- циированное с наибольшим значением в F^, младшим по отношению к д„ скажем а*. Следовательно, в процессе включения а, нам требуется осуществить также поиск и а*. Заметим, однако, что этот поиск не требует никаких дополнительных доступов, т. к. а* располагается на пути, ведущем в то место, где должно быть включено а,. На уровне i+2 сыновье множество для ai+i, обозначаемое Fl+t, будет образовывать другое одностраничное В-дерево. Указатель на сыновье множество на уровне 1 + 2, которое должно предшествовать F,+], размещается в корне F". Этот процесс повторя- ется до уровня п + 1. Если «, становится наибольшим значением в сыновьем множестве F,_i, нужен допол- нительный шаг. В этом случае F,— сыновье множество для а,— становится послед- ним в связном списке сыновьих множеств на уровне i— 1, которые ассоциированы с Fj_|. Это влечет за собой изменение указателя RIGHT в корне F^}, и в результате — включает в себя один дополнительный доступ. На последующих уровнях никакие изменения не нужны. Прежде чем обсудить случай, когда «, становится наименьшим значением в F,_], вве- дем одно определение. Для данного ключа д, в В-дереве X назовем ближайшим левым соседом, а, — наи- больший ключ, меньший чем д; в X, если он существует; будем обозначать его через д,*. Кроме того, если Р обозначает корень В-дерева в нашей структуре, то LEFT(F) hRIGHT(B) суть функции, которые порождают соответственно указатели LEFT и RIGHT. Рассмотрим теперь случай, когда а, становится наименьшим значением в F,_t. Для того чтобы включить В-дерево F, с единственной страницей на подходящее место на уровне i + 1, необходимо иметь доступ к корню В-дерева F. Очевидно, что нет пути, чтобы достигнуть F из F,-]. Но если д,_| имеет ближайшего левого соседа и указатель сыновьего множества /у_], соответствующий д*_|; сохраняется во время поиска сверху вниз по структуре дерева MDBT, то корень дерева F достижим с одним дополни-
Гпава 6. Информационные деревья 511 тельным доступом. В самом деле, в этом случае F может быть получен применением функции RIGHT к корню /7.1. Предположим, что ни один из ближайших левых соседей а* не существует на уров- нях j, k<j < i. Другими словами, для k<j <i есть наименьшее значение в соответ- ствующем В-дерсве, а ак есть последнее значение на нашем пути поиска, имеющее ближайшего левого соседа ак. Тогда из тех же самых соображений ясно, что если указатель сыновьего множества X = /7, сопоставленный ак, сохранен, то доступ к корню F был бы возможен. Чтобы достичь Fh достаточно применить функцию RIGHT(z - к + 1) раз, что соответствует i - к + 1 дополнительным доступам. Количество применений функции RIGHT определяет число необходимых дополни- тельных доступов, когда а, становится наименьшим значением в F,^. Ее запуск, од- нако, происходит после того, как эффективно достигнут уровень i. Это делает воз- можным уменьшить число необходимых дополнительных доступов; если а, не суще- ствует на уровнях k<j< I, но существует а'(к<1<1), то /7 стал бы указателем, направленным в данный момент в X. Эта модификация X не требует дополнительных затрат, а количество применений функции RIGHT будет уменьшено до i-1+ 1. Что- бы суммировать сказанное, введем следующее определение. Положим если ак существует, а а* не существует, для k<j<i(RIGHT будет применяться i-k+\ раз, чтобы получить предшественника /\); если а* существует (F, должно быть включено после F*). Один дополнительный шаг, когда а, становится наибольшим значением, необходим, когда а, становится наименьшим значением в F,_]. Указатель LEFT в корне F,_] дол- жен быть изменен, чтобы отразить тот факт, что сыновье множество F, для а, стано- вится первым множеством в подсписке сыновьих множеств на уровне i + 1 с предком в F,_|. Наконец заметим, что число доступов из уровня i + 1 на уровень и одно и то же во всех случаях. Рассмотрим алгоритм, который для данной записи с комбинацией ключей «„ а2,а„ проверяет, существует ли эта комбинация в справочнике и если нет, то включает ее в структуру MDBT. Алгоритм использует следующие переменные: Р — указатель на корень В-дерева, в котором идет поиск; В(Р) — В-дерсво, адресованное указателем В; Fk — F-указатель, ассоциированный с ключом ак, FI — F-указатель, ассоциированный с ключом «**; X—указатель на корень В-дерева. Для упрощения алгоритма предполагаются выполненными следующие соглашения относительно применимости функций RIGHT и NEXT к вершине А-, чей адрес дается указателем LEVEL(Z): RIGHT(A) = LEVEL(z + 1) и NEXT(A) = X.
512 Часть II. Применение графов и граф-моделей проц ДОБАВИТЬ= 1. % Инициализация % X := LEVEL(1); Р := корень дерева MDBT; /:= 1. 2. % Поиск наибольшего префикса ai, а2, ... а,_1 комбинации ai, а2,.... а„, существующего в справочнике % 3. пока / < л цикл 4. если а, в В(Р) то Р := F, иначе начать включение все; 5. если а', в В(Р) то X := F) все; 6 /:=1+1; все 7. % Включение а, и нахождение правильной позиции на уровне / + 1 для размещения F, % 8. Включить а, в В(Р); 9. Запросить память для п + 1 - / страниц с адресами F,, .... Fn; 10. если а,’ в S(P) то X := F*, 11. иначе % а, становится наименьшим значением % 12. пока NEXT (X) * LEFT(P) цикл X := RIGHT(X) все; 13. LEFT(P) := F,; 14. если а — самое большое значение в S(P) то RIGHT(P) := F, все все; 15. % Включение значений а/+1, .... am, в справочник % 16. пока i < п + 1 цикл 17. Включить а,+1 в F(; NEXT(fi) := NEXT(X); 18. NEXT(X) := F,; X := RIGHT(X); 19. LEFT(F,) := RIGHT(F) := Fh1; / := / + 1; все все Средняя трудоемкость включения записи в базу данных D равна О(р log TV), где N— число записей в базе данных, ар = max(log2/ logc„), где с,— среднее число потом- ков в В-дереве порядка т,. Удаление записи Пусть а2,а„— значения, которые встречаются в подлежащей удалению записи R. Предположим, что а,+1, а,,2, а„— единственные элементы в соответствующих /J-деревьях, так что последние могут быть сведены к своим корням, которые содер- жат по единственному ключу. Тогда, если удаление R приведет в результате к пустой странице доступа, все ключи ап а,,{, ..., а„ станут "негодными" из-за удаления R. т. к. не будет существовать ни одной записи с комбинацией at, а2, ..., altl, а,,. Но суще- ствуют записи с префиксом щ, а2, ..., а,-}. Следовательно, страницы, соответствую- щие ам,а,„ и страницы доступа могли бы быть возвращены в свободный резерв. Если мы находим, что может быть сделано восстановление хранения, то на этом шаге наша стратегия совершенно аналогична стратегии, принятой в алгоритме включения. Страница F, может быть легко восстановлена, т. к. ее предшественник X = есть сыновье множество, ассоциированное с а' — ближайшим левым соседом В проти- воположность этому, если а* не существует, но существует то X получается при-
Гпава 6. Информационные деревья 513 менением функции RIGHT к корню i — сыновьего множества, ассоциированного с а*_|- Общий случай включает тот же самый процесс модификации X, что и в алго- ритме включения. Опишем алгоритм удаления. проц УДАЛИТЬ = 1. % Инициализация % X := LEVEL(1); Р := корень дерева MDBT; / := 1. 2. % Поиск а, и а', / = 1,.., л % 3. пока / < л цикл 4. если а, в В(Р) то Р := F,; 5. если а, — не единственное значение в В(Р) то 6. j := /: Q := Р; % j следует за / % все 7. иначе % значение отсутствует % все; 8. если а* в В(Р) то X := Fj все i := / + 1; все; 9. % В конце этого цикла Q указывает на S-дерево, содержащее а7, для которого все В-деревья, открытые для доступа на последующих уровнях, содержат только одно значение % 10. % Удаление an+i из соответствующей страницы доступа и, если она становится пустой, то удаление также и а; % 11. Удалить ап+1 из В(Р); 12. если В(Р) не пусто то стоп все; 13. Удалить а, из S(Q); 14. если а* нет в B(Q) то 15. пока NEXT(X) * LEFT(Q) цикл X := RIGHT(X) все все; 16. % Возвращение в свободный резерв одностраничных В-деревьев, если таковые есть % 17. /;=;+1; 18. пока j < л + 1 цикл 19. у := NEXT(NEXT(X)); Освободить страницу NEXT(X); 20. N ЕХТ(Х) := у X: = RIGHT(X); все все Трудоемкость алгоритма удаления составляет О(р log X). kB-деревья Эти деревья порядка т, т > I, являются обобщением В-деревьев порядка т для хранения многомерных данных. Они почти полностью аналогичны рассматривав- шимся деревьям MDBT, поэтому ограничимся лишь краткими пояснениями. Можно легко увидеть, что IB-деревья порядка т суть те же самые В-деревья порядка т. В В-деревьях порядка т каждая вершина, исключая корень, содержит ,v ключей, <.v < т. В АВ-деревьях, однако, могут существовать вершины, содержащие ме- 17 Зак 202
514 Часть II. Применение графов и граф-моделей нее Гда/2~| ключей (представляющие собой структурные нарушения), при условии, что эти структурные нарушения "поддерживаются" EQSON-поддеревьями на единицу меньшей размерности основного дерева, которые присоединены к вершинам, где имеют место структурные нарушения. Структурное нарушение, вызываемое верши- ной W на высоте h, поддерживается поддеревом, если высота поддерева равна h или больше. Рис. 6.46. Двумерное 2-3-дерево: а — 2В-дерево порядка единицы, б — двумерное 2-3-дерево, в котором каждое пустое левое, среднее или правое поддерево вершин представляется цепью из h -1 унарных вершин без ключей На рис. 6.46, а изображено 2/3-дсрево порядка единицы, т. е. двумерное 2-3-дерево. Это дерево хранит следующие элементы данных: (а,1), («,3), (л,7), («,9), (Ь,2), (Ь,4), (Ь,5), (с,1), (с,2), (J,l), (J,3). Как и в 2-3-дереве, вершина N, хранящая г ключей, имеет г + 1 поддеревьев, которые все хранят ключи той же самой размерности, что и хранящиеся в 7V. Кроме того, каж- дый двумерный ключ в вершине имеет одномерное EQSON-поддерево. Таким обра- зом, поддеревья с корнями в вершинах В и С (см. рис. 6.46, а) суть EQSON- поддеревья ключей а и Ь соответственно. Заметим, что левое и среднее поддеревья вершины А пусты. На рис. 6.46, б показано то же самое двумерное 2-3-дерево, что и на рис. 6.46, а, за исключением того, что N высоты h представляется цепью из h - 1 унарных вершин без ключей (показаны на рисунке перекрещенными вершинами). На рис. 6.46, б вид-
Глава 6. Информационные деревья 515 но, что поддерево с корнем в В есть "присоединенное поддерево на единицу меньшей размерности" вершин Р, Q, R и S. Аналогично, поддерево с корнем в С есть "присое- диненное поддерево на единицу меньшей размерности" вершин R, S, Т и D. Струк- турные нарушения, имеющие место в вершинах Р, Q, R, S, Т, U и V, допускаются из- за того, что каждое из этих нарушений структуры поддерживается соответствующим присоединенным EQSON-поддеревом меньшей размерности. 6.2.3. Деревья множественных атрибутов Дерево множественных атрибутов определяется следующим образом: A-мерное де- рево множественных атрибутов (МАТ) для множества записей, характеризующихся к атрибутами А (,..., Ак, есть дерево глубины к со следующими свойствами: П МАТ имеет корень на уровне 0; □ каждый потомок корня есть {к - 1)-мерный МАТ на (А - 1) атрибутах /Ь,..., Ак для подмножества записей, имеющих один и тот же атрибут A i; это значение атрибута А\ есть значение корня соответствующего (к — 1)-мерного дерева МАТ; □ вершины — потомки корня — упорядочены в соответствии с возрастанием их значений; это множество вершин-потомков называется сыновьим множеством. На рис. 6.47, а показано множество записей, а соответствующее ему дерево МАТ — на рис. 6.47, в. Заметим, что корень на уровне 0 не имеет никакого значения. Каждая вершина на уровне i, i = 1,2,..., к, соответствует значению атрибута А,, и это зна- чение есть значение вершины. Таким образом, атрибуты At, А2.Ак формируют иерархию уровней от 1 до к. Важным свойством структуры МАТ является то, что каждое сыновье множество упорядочено. Это есть результат того свойства, что сор- тировка множества записей по атрибутам естественно индуцирует деревообразную структуру, как показано на рис. 6.47, б. Следовательно, абстрактное дерево МАТ может рассматриваться как дерево, построенное следующим образом: □ записи сортируются в порядке возрастания по их атрибутам; □ начиная с первого атрибута, все элементы атрибута, имеющие одно и то же зна- чение, объединяются в вершину. Этот процесс рекурсивно исполняется для каждого подмножества записей, которые имеют одно и то же значение первого атрибута. Конструкцию МАТ можно пояснить в терминах геометрических понятий. Поддерево МАТ на атрибутах А2, А3, ..., Ак, порожденное способом, указанным во втором свой- стве определения МАТ, соответствует множеству точек, которые лежат в гиперпло- скости в пространстве данных. Уравнение этой гиперплоскости есть At = а^ где а, — значение атрибута А{, соответствующее корню поддерева МАТ. Так как гиперпло- скость в пространстве размерности к соответствует (к - 1)-мерному подпространству, каждое рекурсивное порождение поддерева МАТ выполняется на пространстве меньшей размерности. Тот же самый эффект обнаруживается в алгоритмах поиска, которые работают рекурсивно на пространствах меньшей размерности.
516 Часть II. Применение графов и граф-моделей в) Рис. 6.47. Дерево множественных атрибутов: а— множество записей, б — индуцированное им древовидная структура, в — соответствующее ему дерево МАТ
Глава 6. Информационные деревья 517 Другое важное свойство состоит в том, что каждая запись или точка представляются единственным путем из корня в соответствующую концевую вершину. Из-за этого свойства профиль МАТ для данного множества записей полностью зависит от появ- ления различных значений атрибута в записях. В общем случае размеры различных сыновьих множеств зависят от множества входных записей и соответствующих зна- чений атрибутов. В случае симметричных деревьев МАТ, у которых распределение данных симметрично относительно атрибутов, средний размер сыновьего множества равен O(7VIrt), где N=st s2, st- Генерация справочника Структура данных МАТ линеаризуется для формирования справочника. Справочник определяет способ организации уровней и реализации сыновьих множеств. Структу- ры данных, такие как MAT, MDBT, АВ-дсревья и др., могут быть реализованы с использованием указателей. Ответ на запрос вызывает прохождение указателей. В общем случае не делается никаких предположений о способе организации указате- лей. Реализация с использованием указателей эффективна, когда структура данных размещена в оперативной памяти. Но когда справочник размешен во внешней памя- ти, где передача информации осуществляется страницами, случайность в организа- ции реализации указателей приводит к хранению многих ненужных страниц. Напри- мер, рассмотрим случай, когда вершины сыновьего множества располагаются в раз- личных страницах во внешней памяти. Эта ситуация может возникнуть, когда сыновье множество порождается динамическими включениями записей после завер- шения построения статической структуры. В этом случае поиск в сыновьем множест- ве размера л может привести к обращению к O(log .s) страницам во внешней памяти. Но если сыновье множество реализуется на одной странице или на постоянном числе страниц, то тогда поиск включает 0(1) обращений к страницам внешней памяти. Так как страница внешней памяти загружена в оперативную память, поиск может быть выполнен в сыновьем множестве для требуемого значения. Эта ситуация возникает во многих приложениях (графика, вычислительная геометрия и т. д.), где большой размер данных вынуждает хранить информацию во внешней памяти. Абстрактная структура МАТ может быть реализована с использованием указателей, рассмотрим такую организацию, в которой вершины, соответствующие сыновьему множеству, хранятся вместе. Основная идея состоит в объединении в кластер вер- шин, к которым, вероятно, может потребоваться доступ при ответе на запрос. В за- просе с полным соответствием вершины в сыновьем множестве ищутся по значению. В запросе с частичным соответствием либо для заданного значения ищется сыновье множество, либо в сыновьем множестве проводится поиск. В объемном запросе ищутся вершины внутри специфицированного интервала. Для того чтобы ответить на приведенные запросы, введем понятие линеаризации, которая даст нам возможность хранить структуру данных в форме таблицы. Существует два типа линеаризации: по поиску в глубину и по поиску в ширину. Любая из них может делаться как сверху вниз, так и снизу вверх. Метод сверху вниз более эффективен, нежели снизу вверх. Поскольку при ответе на запрос метод сверху вниз требует просмотра меньшего чис- ла вершин. При линеаризации по поиску в глубину вершины, соответствующие по- лям записи, хранятся вместе, как показано на рис. 6.48, а. Числа рядом с вершиной указывают номера вершин в справочнике. Это эффективная техника для обработки
518 Часть II. Применение графов и граф-моделей запросов на точный поиск, когда в лучшем случае ответ может быть получен за одно обращение к внешней памяти (в предположении, что на одной странице может хра- ниться к вершин). Однако в худшем случае необходимо к обращений. Но это не дела- ет естественным поддержку запросов с частичным соответствием и объемных запро- сов, при которых элементы сыновьего множества не хранятся вместе. При линеари- зации по поиску в ширину вершины, соответствующие сыновьему множеству, хранятся вместе, как показано на рис. 6.48, б. Этот метод естественно поддерживает запросы с частичным соответствием и объемные запросы. 6) Рис. 6.48. Способы линеаризации: а — по поиску в глубину вершины, б — по поиску в ширину вершины Процедура DIR-GEN Прежде чем предоставить описание процедуры, предназначенной для построения справочника на основе линеаризации по поиску в ширину, рассмотрим некоторые особенности ее работы. Оператор 2 процедуры DIR-GEN вычисляет переменную base[i], I = 1,2,..., к + I, такую, что каждая вершина справочника лежит между base[i] и base[i + 1] - 1. Эти переменные нужны для хранения полей значений первый сын и последний сын в процедуре DIR-GEN. Основной вклад во время ее работы алгорит-
Гпава 6. Информационные деревья 519 ма дает сортировка. После ввода записей и сортировки делается два прохода по от- сортированным записям, один для процедуры COMPUTE-BASE и один для операто- ров 3—11 процедуры DIR-GEN. Если вводимые данные располагаются в оператив- ной памяти, то сортировка требует O{kN log (АЛ)) сравнений. Процедура COMPUTE- BASE требует O(kN) сравнений или доступов к памяти. Это объясняется тем, что оператор 6 процедуры COMPUTE-BASE и оператор 6 процедуры DIR-GEN включа- ют самое большее к сравнений для каждой записи. Можно показать, что оператор 8 процедуры COMPUTE-BASE и операторы 8 и 9 процедуры D1R-GEN будут испол- няться самое большее к раз для каждой записи. Следовательно, сложность процедуры DIR-GEN равна O{{kN) log(AA) + 2A7V) = O{{kN) log {kN)). Если каждое сравнение за- писей тратит единицу времени, то сложность равна O{N log N). Если вводимые данные располагаются во внешней памяти, то трудоемкость опреде- ляется доступами к страницам во время сортировки. Другие части процедуры делают два последовательных прохода по отсортированным данным, и в течение этих двух проходов производится О{т) обращений к странице, где т есть число страниц, в ко- торых хранятся данные. Следовательно, используя стандартную технику внешней сортировки, генерация справочника может быть сделана с О{т log т) обращениями к страницам. проц DIR-GEN = 1. отсортировать файл входных данных по всем к атрибутам; 2. COMPUTE-BASE; 3. Читать первую запись; 4. повторять 5. Читать следующую запись; 6. Сравнить ее с предыдущей записью, чтобы получить L — наибольший уровень, на котором значения атрибута различны; 7. для j от L до к цикл 8. Заполнить поле значение все; 9. для j от L + 1 до к цикл 10. Заполнить поля первый_сын и последний_сын; все 11. до обработки всех записей все все проц COMPUTE-BASE = 1. для / от 1 до к + 1 цикл base[t] := / все; 2. Читать первую запись, 3. повторять 4. Читать следующую запись; 5. Сравнить прочитанную запись с предыдущей, чтобы получить L — наибольший уровень, на котором значения атрибута различны; 6. для j от L до к + 1 цикл base[/] := base[/J + 1 все 7. до обработки всех записей все; 8. для j от 2 до к + 1 цикл base[/] = base\j] + base[j -1] все все
520 Часть II. Применение графов и граф-моделей 6.2.4. Парадигмы для МАТ-структур Алгоритмы поиска в структуре МАТ для всех видов запросов используют понятие кластеризации данных для улучшения эффективности в среднем различных поиско- вых алгоритмов. Это достигается хранением вместе вершин, которые с большой до- лей вероятности могут понадобиться при ответе на запрос. Анализ эффективности проводится для двух случаев: когда справочник располагается в оперативной памяти и во внешней. Линеаризация по поиску в ширину гарантирует, что сыновьи множества располага- ются последовательно в оперативной памяти и на них возможен бинарный поиск. Когда справочник располагается во внешней памяти, эта кластеризация помогает в уменьшении числа просматриваемых страниц. Мы предполагаем, что каждое сы- новье множество занимает не более фиксированного числа страниц во внешней па- мяти. Предполагаем также, что сыновье множество может быть полностью загруже- но в оперативную память, когда формируется ответ на запрос. Можно показать, что, когда справочник располагается в оперативной памяти, МАТ также эффективен, как и другие структуры типа AS-деревьев, MDBT и т. д., но эффективнее, когда справоч- ник располагается во внешней памяти. к Определим запрос Q как Q = р]д,, где q, есть классификатор атрибута А,. Для запро- /=1 са с точным соответствием q, определяет значение Ah i = 1, 2, ..., к. Для объемного запроса q, специфицирует интервал [/„ и,] для атрибута At, i = 1, 2,..., к, где к и г/, спе- цифицируют нижнюю и верхнюю границы изменения атрибута соответственно. Для запроса с частичным соответствием каждый уровень может быть как специфициро- ван, так и нет. Для специфицированного уровня I, I = 1,2, ..., к, q, определяет значе- ние А,. Для неспецифицированного уровня q, не накладывает никакого ограничения на А,. Говоря об ответе на запрос, будем считать, что пространство записей с к атри- бутами порождает A-мерное пространство, а объемный запрос описывает ориентиро- ванный по координатным осям гиперпараллелепипед. Ответ на объемный запрос соответствует отысканию точек, содержащихся в таком гиперпараллелепипеде. В структуре МАТ при ответе на любой запрос обработка любого атрибута уменьшает размерность пространства, в котором должен быть произведен поиск, на единицу. Основным понятием при поиске в МАТ является понятие "иерархического спуска", когда запрос обрабатывается уровень за уровнем, начиная с корня. На каждом уровне j,J = 1, ..., А агрегируются вершины, которые удовлетворяют "частичному" запросу J Эти вершины называются классифицированными. Классифицированные вер- /=1 шины на уровне А содержат указатели на физические записи, которые удовлетворяют запросу. При дальнейшем обсуждении этого вопроса мы ограничимся линеаризацией по поиску в ширину. проц MAT-SEARCH(/eve/, qnodes) = 1. tempset := 0;
Глава 6. Информационные деревья 521 2. для каждой п е qnodes цикл 3. добавить к tempset всех сыновей п, которые удовлетворяют qievei, все; 4. если level< кто 5. MAT-SEARCH(/eve/+ 1, tempsety 6. иначе 7. для каждой п е tempset_ цикл 8. отыскать указатель на запись все 9. все; все Инициализирующий вызов имеет вид MAT-SEARCH(1, {root}). Когда справочник располагается во внешней памяти, исполнение строк 2 и 3 критично по отношению к числу обращений к страницам. Множество qnodes упорядочено, и обращение к нему идет в этом порядке. Это приводит в результате к тому, что доступ к сыновьим мно- жествам в структуре МАТ осуществляется последовательно слева направо. Этот тип доступа эффективен, когда все множества небольшого размера и в одной странице их может собраться несколько штук. Такой сценарий встречается при ответе на объем- ный запрос. Фактически, используя упорядочение в соответствии с поиском в шири- ну и упорядоченное множество qnodes, можно эффективно поддерживать последова- тельные доступы к справочнику. Запрос на точный поиск Для запроса на точный поиск на любом уровне j существует только одна вершина, 7 которая удовлетворяет частичному запросу f'jg,, т. к. последний специфицирует 1=1 единственную комбинацию значений атрибутов в "частичном" МАТ, ограниченном первыми j уровнями. Следовательно, строка 3 процедуры MAT-SEARCH исполняет- ся только раз для каждого уровня. Для каждого исполнения строки 3 выполняется бинарный поиск на сыновьем множестве для специфицированного значения атрибу- та. Следовательно, в худшем случае сложность запроса на точный поиск равна 0{к log N), а в среднем — O(log N). Если справочник располагается во внешней памяти, то на каждом уровне проводим поиск не более чем на с страницах, соответствующих сыновьему множеству класси- фицированной вершины на предыдущем уровне. Следовательно, число обращений к страницам для точного поиска равно О(ск) = О(к). При использовании поиска в ши- рину для любого запроса на точный поиск всегда просматривается ск страниц. При использовании поиска в глубину в лучшем случае для ответа на запрос о точном по- иске достаточно одной страницы. В этом случае все классифицированные вершины, соответствующие запросу, лежат в одной странице. Но в худшем случае нужно про- смотреть O(.v, + s2 + ... + -V*) страниц. В этом случае классифицированные вершины являются последними вершинами в их сыновьих множествах. Используя характери- зацию в среднем, можно утверждать, что в худшем случае число доступов к страни- цам для запроса на точный поиск равно O(kNllk). Интересно отметить, что при реали-
522 Часть II. Применение графов и граф-моделей зации МАТ с использованием указателей и без предположения о кластеризации вер- шин необходимо много доступов к страницам. Запрос на поиск с частичным соответствием (частичный поиск) Максимальное число записей, удовлетворяющих частичному запросу, который спе- цифицирует I уровней, равно г, • t2 •... tk, где t, = 1, если А, специфицировано, и t, = v, (число значений атрибута А,), если А, не специфицировано. Можно показать, что число записей, которые удовлетворяют данному частичному запросу, равно O(Nl~llk) для однородно распределенных данных. В строке 3 алгорит- ма MAT-SEARCH для специфицированных уровней выполняется бинарный поиск в сыновьих множествах. Для неспецифицированных уровней классифицируем целиком сыновье множество. В худшем случае для нашего алгоритма первые к— t атрибутов не специфицированы, а каждая классифицированная вершина на уровне k-t дает увеличение на одну классифицированную вершину на каждом последующем уровне. Следовательно, для каждого уровня j, (к-1 + 1) <j < к, имеем <9(7VI-Ift) множеств, где нужно провести поиск, и на каждом уровне могут быть <9(А|-|/*) классифицирован- ных вершин. Таким образом, стоимость ответа на частичный запрос равна 0(5,52 -sk-l (10g5*-r+, + —+log5^)) = O(rAI-I/* logtTV17*)). Заметим, что это выражение стремится к O(logTV) с ростом числа специфицирован- ных атрибутов. Если справочник располагается во внешней памяти, то число доступов к страницам, соответствующим первым к - t неспецифицированным уровням, равно O(Nl^'~l^lk) — по одному доступу к странице на каждое сыновье множество. Число доступов к стра- ницам на последующих t специфицированных уровнях равно O(tNl^'~,Vk). Следо- вательно, полное число доступов к страницам равно О(гАк'-|)Л). С ростом числа специфицированных уровней это выражение стремится к O(kNllk). Если линеаризация не предполагается, то каждая классифицированная вершина может вызвать уве- личение числа доступов к страницам и, таким образом, оно становится равным О(1М*~"к log(7Vlft)). Если для линеаризации используется упорядочение в соответствии с поиском в глубину, то можно показать, что число доступов к страницам равно O(tN'~'lk). Реализация линеаризации по поиску в ширину незначительно лучше линеа- ризации по поиску в глубину. Однако обе линеаризации более эффективны, чем про- извольная реализация. Объемный запрос Анализ эффективности объемного запроса в худшем случае носит чисто теоретиче- ский характер, поскольку получается, что в худшем случае теоретически требуется просмотр всех N записей, что совершенно нереально на практике. Пусть a— наибольшее число классифицированных вершин в каждом сыновьем мно- жестве, где был произведен поиск при объемном запросе, и пусть классифицирован- ная доля р определяется как _ a + a2 + ... + ak _ a(ak -1) Р~ N ~ (a-\)N'
Глава 6. Информационные деревья 523 Для достаточно больших а имеем р = a / N. Классифицированная доля р дает среднее число классифицированных вершин и поэтому определяет стоимость объемного по- иска. Средние стоимости объемного поиска сведены в табл. 6.2, где А1 обозначает число классифицируемых записей. Таблица 6.2. Средние стоимости объемного поиска Классифицированная доля р Стоимость запроса по памяти Оперативной Внешней ([AVA]) ([logA/A]) ([log log N/N]) ([C/N]) □(A1"1'* log (AIZ*) + /С|) O(logA+/t,) O(log(/V*+logA)+/4) O(log (Alz*) + А|) О(А1-,/*) O(log А) O(log (AIZ* + log А)) O(log (Alz*)) Библиографический комментарий Развитие данного направления и достаточно подробная библиография представлены в книгах [6—8, 10J и обзоре [4]. По существу, первой работой по сбалансированным деревьям с целью применения их для ор- ганизации больших массивов информации была работа Г. М. Адельсона-Вельского и Е. М. Ландиса [1]. Введенные ими балансированные по высоте деревья были позднее названы АВЛ-деревьями [7]. Их описание включено в большинство издаваемых книг по вопросам хра- нения информации и организации поиска [6—10], а также библиографию к обзору [4]. /3/3-деренья были введены в работе [33] и подробно охарактеризованы в [5, 10]. Описание 2-3-деревьев заимствовано из [2]. //-деревья и //В-деревья, а также //В-деревья были введены в работах [29, 34], ^-деревья малой высоты— в [28], 1-2-братские деревья— в [35]. М-деревья были введены в [12], о возможностях их дальнейших применений изложено в [13] и последующих работах этого же автора. /3-деревья были введены в рассмотрение Р. Бейером и К. Мак-Крайтом в 1972 г. [11] и подроб- но исследовались в [7], [5]. Там же были введены В’-деревья, позволяющие использовать до 2/3 имеющегося в каждой вершине пространства. Вопросы программирования алгоритмов работы с В-деревьями рассматривались в [7] и [3] (Модула-2). Следует отметить также работу [18], где рассматривались формальные спецификации бинарных деревьев и В-деревьев и алго- ритмы для работы с ними. Плотные m-арные деревья основаны на понятии братского дерева и позволяют строить деревья с наперед заданной плотностью заполнения вершин. Этот тип де- ревьев был предложен в 1979 г. в работе [17]. Организация поиска слов внутри вершин /3-дерева изучалась в работе [25]. Слабые В-деревья были введены К. Мельхорном и изучались в работах [20, 30]. Сильные /3-деревья были введены в рассмотрение в работе [21]. Кроме этих типов деревьев известны компактные В-деревья [16, 39], а также цифровые В-деревья [26]. Компактные В-деревья — это деревья, у которых число страниц минимально. Алгоритм конструирования компактного /3-дерева для случая упорядоченных ключей предложен в [16]. Этот алгоритм удобно исполь-
524 Часть II. Применение графов и граф-моделей зовать, например, для реструктурирования упорядоченных структур данных или слияния двух В-деревьев. просматривая их параллельно и одновременно строя новое дерево. Цифровым S-деревом называется такая организация файловых индексов, которая обеспечивает эффективное выполнение как последовательных, так и случайных операций доступа. Во мно- гих отношениях они аналогичны обычным S-деревьям. Их преимущество состоит в том, что они допускают значительно более мощное ветвление в каждой вершине, уменьшая тем самым высоту дерева для заданного размера файла Результатом этого является сокращение стоимо- сти случайного поиска в файле. Ветвление вершин S-дерева существенно увеличивается за счет введения многостраничных вершин. Уникальной особенностью цифрового S-дерева явля- ется то, что для каждой операции поиска должна исследоваться только одна страница верши- ны. Для этого применяется метод, аналогичный используемому в расширенном хэшировании, но который не требует выполнения операций хэширования. Интерес представляет также страничное ЛВЛ-дерево, изучавшееся в [15]. Использование АВЛ- деревьев для двухуровневой памяти требует разбиения их на поддеревья, каждое из которых хранится в отдельной странице памяти. Количество страниц, которое нужно пройти при дви- жении от корня к вершине, называется страничной длиной пути; страничной высотой дерева, или p-высотой, называется наибольшая из страничных длин его вершин. Страничное АВП- дерево обладает тем свойством, что все листья имеют одну и ту же страничную длину пути, которая, в свою очередь, равна p-высоте дерева без единицы. Для дерева с и вершинами p-высота удовлетворяет неравенству Л < 1 + log„ +10 + тг«-1)) 1 и где [я]— наибольшее число вершин на странице, ап,— число вершин в левом подде- реве. причем я, = F-k-2- I, где /д_2 есть число Фибоначчи, определяемое из условия Ft [ п ] + 2 < F*_,. Страничное /lS./7-дерево во многом близко к S-деревьям; при некоторых условиях они подоб- ны в том смысле, что одни и те же ключи группируются Одним и тем же способом в страницы и имеют одну и ту же страничную структуру. Более того, S-деревья могут быть преобразованы в подобные страничные ЛВЛ-деревья. Главное отличие между ними состоит в выборе "средне- го" ключа при расщеплении страницы. В S-деревьях страница делится на две одинаковые час- ти, в страничных zlS.S-деревьях в качестве "среднего” ключа берется корень поддерева, хра- нящегося в странице Имея примерно одинаковые характеристики страничные АВЛ-деревья допускают более легкое изменение данных нежели S-деревья с последовательной организаци- ей страницы. Укажем также на работу [36], где рассматриваются S-деревья с новой мерой оптимальности, равной количеству просматриваемых вершин (WJ-оптимальные S-деревья). Поведение В-де- ревьев в среднем изучалось в работе [27]. Анализу В-дсревьев посвящены также работы [14, 32, 36. 38]. Описание деревьев MDBT дано по работе [37], структуры МАТ - в обзоре [22], содержащем анализ современного состояния теории и практики многомерных деревьев и обширнейшую библиографию по этому вопросу. Первоначально деревья МАТ были рассмотрены в работах [23, 40]; АВ-деревья были введены в работах [19 24]. Следует также упомянуть работу [41], в которой были введены и исследованы многомерные ЛВЛ-деревья.
Глава 6. Информационные деревья 525 Список литературы 1. Адельсон-Вельский Г. М., Ландис Е. М. Один алгоритм организации информации // Докл. АН СССР. — 1962. — Т. 146, № 2. — С. 263 266. 2. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. — М.: Мир, 1979. 3. Вирт Н. Алгоритмы и структуры данных. — М.: Мир 1989. 4. Евстигнеев В. А. Применение бинарных деревьев для организации больших массивов ин- формации (обзор) // Прикладная информатика. — М., 1981. — Вып. I. — С. 170 — 211. 5. Евстигнеев В. А. Применение теории графов в программировании. — М.: Наука, 1985. 6. Евстигнеев В. А., Касьянов В. Н. Теория графов. Алгоритмы обработки деревьев. — Но- восибирск: Наука, 1994 7. Кнут Д. Искусство программирования для ЭВМ. — М.: Мир, 1978. — Т. 3: Сортировка и поиск. 8. Кормен Т., Лейзерсон Ч., РивестР. Алгоритмы: построение и анализ.— М.: МЦНМО, 1999 9. Лаврове. С., Гончарова Л. И. Автоматическая обработка данных Хранение информации в памяти ЭВМ. — М : Наука, 1971. 10. РейнголдЭ., Нивергельт Ю., Део Н. Комбинаторные алгоритмы. Теория и практика.— М.: Мир, 1980. 11. Bayer R., McCreight С. Organization and maitenance of large ordered indexes // Acta In- form — 1972. —Vol. 1.N3.-P. 173— 189. 12. Bentley J. L. Multidimensional binary search trees in database applications// IEEE Trans, on Software Eng. — 1979. — Vol. SE-5, N 4. — P. 333 — 340. 13. Bentley J. L. Multidimensional binary search trees used for associative searching// Comm. ACM. — 1975. —Vol. 18,№9, —P. 509 — 519. 14. Brown M. R. Some observations on random 2-3 trees// Inform. Process. Let— 1979.- Vol 9, —P. 57 —59. 15. Casarini F., Soda G. Binary trees paging// Inform. Systems.-— 1982.— Vol. 7, N 4.— P. 337 — 344. 16. Cesarini F., Soda G. An algorithm to construct a compact В-tree in case of ordered keys // In- form Process. Let. — 1983. — Vol. 17, N 3. — P. 13 — 16. 17. Culic K., Oilman Th., Wood D. Dense multiway trees. — Comp. Sci. Tech. Rep. 79-GS-5. McMaster Univ., Ontario, 1979. 18. Fielding E., Jones C. Program design by data refinement // D.Bjorner, С. B.Jones. Formal Speci- fication and Software Development. Chapt. 10. — Prentice-Hall Intern., 1982. — P. 323—352. 19. Gueting R. H., Kriegel H. P. Multidimensional b-tree: an efficient dynamic file structure for ex- act match queries// Proc. 10th G1 Annual Conf, Informatic Fachberichte.— Springer Verl., 1980, —P. 375 —388. 20. Huddleston S., Mehlhorn K. A new data structure for representing sorted lists // Acta Inform. — 1982, —Vol. 2, —P. 157— 184. 21. Huddleston S., Mehlhorn K. Robust balancing in B-trees // Leet. Notes Comput. Sci. — 1981. — Vol 104 — P. 235 — 244.
526 Часть II. Применение графов и граф-моделей 22. Iyengar S. S. а.е. Multidimensional data structures' review and outlook// Adv. Comput.— 1988. — Vol. 27. — P. 69 — 119 23. Kashyap R. L., Subas S. К. C., Yao S. B. Analysis of multiattribute tree database organization // IEEE Trans. Softw. Eng. — 1977. — Vol. SE-2, N 6. — P. 451 — 467. 24. Kriegel H. P., Vaishnavi V. K. Weighted multidimensional В-trees used as nearly optimal dy- namic dictionaries// Proc. 10th Int'l Symp. on Math. Found, of Comput. Sci.— 1981.— P. 410 — 417. 25. Kwong Y.S., Wood D. В-trees: a variant of B-trees.— Comp. Sci. Tech. Rep. 78-CS-18, McMaster Univ., Ontario, 1978. 26. Lomet D. B. Digital В-trees// 7th Int'l Conf. Very Large Data Bases, Cannes, Sept. 9— 11, 1981 — P. 333 — 344. 27. Maruyama K. Index structures for virtual memory — comparison between В-trees and M-trees // IBM Res. Rep. RC 5258, 1975. 28. Maurer H. A., Ottman Th., Six H.-W. Implementing dictionaries using binary trees of very small height // Inf. Proc. Lett. — 1976. — Vol. 5, N 1. — P. 11 — 14. 29. Maurer H. A., Wood D. Zur Manipulation von Zahlenmengen // Angewandte Informatik. — 1976, —Bd 18,N 4, — S. 143— 149. 30. Mehlhorn K. A new data structure for representing sorted lists // Leet. Notes Comput. Sci. — 1981. —Vol. 100. —P. 90— 112. 31. Miller R. E., Pippcnger N., Rosenberg A. L., Snyder L. Optimal 2-3 trees // SIAM J. Comput. — 1979. — Vol. 8. — P. 42 — 59. 32. Mizoguchi T. On required space for random split files// Proc. 17th Annual Allerton Conf., 1979. —P. 211—217. 33. Nievergelt J., Reingold E. M Binary search trees of bounded balance // SIAM J. Comput. — 1973, —Vol. 2,N L —P. 33 — 43. 34. Ottman Th., Six H.-W. Eine neue Klasse von ausgeghchenen Binarbaumen // Angewandte In- formatik. — 1976. — Bd 18, N 9. — S. 395 — 400. 35. Ottman Th., Wood D. 1-2 brother trees or AVL trees revisited // Comp. Sci. Techn. Rep. 79-CS- 11. — Hamilton: McMaster Univ., 1979. 36. Ouskel M., Scheuermann P. Multidimensional В-trees: analysis of dynamic behavior// BIT. — 1981 — Bd21,N4 —P. 401 — 418. 37. Quitzow К H., Klopproge M R. Space utilization and access path length in B-trees // Inform. Systems. — 1980. — Vol. 5. — P 7 — 16. 38. Rosenberg A. L., Snyder L. Time and space optimality in B-trees// ACM TODS.— 1981.— Vol. 7, N L — P. 174— 183. 39. Subas S. К. C., Kashyap R. L. Database organization — an access and storage method. — Tech. Rep. TREE 75-32, School of Engineering, Purdue Univ., 1976. 40. Vaishnavi V. K. Multidimensional height-balanced trees// IEEE Trans. Comput.— 1984.— Vol. C-33, N 4. — P. 334 — 343. 41. Yao A. С. C. On random 2-3 trees //Acta Inform. — 1978. — Vol. 9. — P. 159 — 170.
ГЛАВА 7 Синтаксические деревья Рассматривая любую знаковую систему (в том числе и язык программирования), обычно выделяют синтаксис— правила построения сообщений в этой системе, се- мантику— правила истолкования сообщений тем, кому они адресованы, а также прагматику, сопоставляющую сообщения желаниям того, от кого они исходят. Важным при определении любого языка программирования является описание тех синтаксических структур, которые приписываются языком каждому из предложений, составляющих язык. Синтаксическая структура предложений — это тот (пока) един- ственный мост, который может использоваться при задании и определении смысла программ. Она позволяет осуществлять автоматически (без привлечения человека) процесс трансляции — эквивалентного (с сохранением семантики преобразуемой программы) перевода программы с одного языка на другой. 7.1. Синтаксис языка и задача фазы анализа Логически трансляция содержит две основные части: анализ и синтез. Первая часть распознает во входном тексте конструкции абстрактной программы, а вторая реали- зует собственно перевод— построение эквивалентной ей выходной программы. Ис- пользуемые подходы при определении языка вызывают разбиение процесса построе- ния абстрактной программы на три последовательно работающих этапа: лексический, синтаксический и контекстный анализ. 7.1.1. Синтаксис языка, лексемы, понятия и атрибуты Всякий язык программирования можно определить как множество предложений — некоторое множество цепочек или конечных последовательностей элементарных единиц из некоторого непустого конечного множества символов, называемого слова- рем или алфавитом. Само собой разумеется, что при таком рассмотрении языка про- граммирования мы задаем только множество символов, которые можно использовать /
528 Часть II. Применение графов и граф-моделей для записи программы, а также класс допустимых или синтаксически правильных программ и при этом никак не касаемся вопроса задания смысла каждой правильной программы. Очевидно, что невозможно и нежелательно задавать множество допустимых про- грамм исчерпывающим их перечислением. Нам нужно, чтобы описание языка было обозримым (заведомо конечным), хотя описываемый язык может быть и бесконеч- ным. Обычный подход, удовлетворяющий этому требованию, состоит в том, что предложения языка образуются по определенным правилам, в совокупности состав- ляющим то, что называют грамматикой языка. Эти грамматические правила припи- сывают предложениям языка некоторую синтаксическую структуру, которая может ^использоваться при задании и определении смысла предложений. Грамматика языка может быть реализована следующими двумя способами Первый способ основан на том, что грамматика имеет вид порождающей системы (разрешения производить некоторые действия), используя которую можно получить (породить) все предложения языка и только их. Примерами порождающих грамматик являются форма записи для задания синтаксиса языка Алгол-60, получившая назва- ние нормальной формы Бэкуса, или формы Бэкуса—Наура (сокращенно БНФ), а также так называемые синтаксические диаграммы, используемые при описании язы- ка Паскаль. Этот способ задания языка программирования ориентируется на челове- ка, поскольку человек использует язык программирования для создания (порождения) программ, решающих поставленную задачу. Однако программы предназначены, главным образом, для их решения на ЭВМ, и возникает задача распознавания синтак- сической структуры уже написанных программ. Второй распространенный метод описания языка связан с использованием в качестве грамматики некоторого алгоритма (предписания производить некоторые действия), который дает возможность для произвольной цепочки (в соответствующем словаре) получать ответ на вопрос, принадлежит ли эта цепочка языку, т. е. является ли она его предложением. Схематизированные устройства, используемые для представления таких алгоритмов, получили название распознавателей. Примером распознавателя является машина Тьюринга. Синтаксическая структура, приписываемая предложениям языка грамматическими правилами, существенно используется при определении семантики языка программи- рования в целом и его отдельных конструкций. Поэтому удобным представляется взгляд на язык программирования как на иерархию конструкций (рис. 7.1), позво- ляющую в удобной для человека нотации оперировать с простыми и составными данными и действиями. Не все языки программирования высокого уровня обладают каждым из приведенных средств, а некоторые языки (например, Ллгол-68) разреша- ют операторам находиться в выражениях. Тем не менее все элементы иерархии ти- пичны для языков высокого уровня и знакомы любому пользователю независимо от того, какой конкретный язык программирования высокого уровня он применяет в своей работе Верхний уровень иерархии образует сама программа — основная единица для транс- ляции и выполнения. Затем идут подпрограммы (процедуры, блоки и т. п.), являю-
Гпава 7. Синтаксические деревья 529 щиеся единицами трансляции, но не обязательно выполнения Подпрограммы обра- зуются из операторов и могут иметь свои собственные (локальные) данные. В свою очередь выражения являются частью операторов и строятся из данных и операций. Программа I Подпрограмма I Операторы I------Выражения --------1 1 1 Данные Операции Функции Рис. 7.1. Иерархия языковых конструкций Операции в языке играют роль вычислительных машинных операций, т. е. тех опера- ций ЭВМ, которые отрабатываются ее вычислителем, а операторы — управляющих операций, т. е. тех, которые в ЭВМ отрабатываются исполнителем. Поэтому обычно собственно операторы, в отличие от операций, не вырабатывают новых значений (языки программирования, в которых это не так, называются языками выражений). Важным свойством языков программирования высокого уровня является их способ- ность образования составных действий: выражений, структурных операторов и под- программ. Выражения, операторы и подпрограммы в языке программирования служат той осно- вой, на которой операции и данные исполняющей машины объединяются в програм- мы и совокупности программ. Это — способы задания сложных действий как встро- енных в исполняющую машину, так и определенных в ней программистом с по- мощью других действий. Хотя использование конструкций в разных языках программирования имеет свою специфику с точки зрения синтаксиса и семантики, тем не менее, в любом языке име- ется определенная согласованность синтаксических и семантических правил построе- ния элементов иерархии из тех конструкций, которые занимают более низкие уровни. Алфавит, используемый для записи языка программирования, ограничивается срав- нительно небольшим множеством литер, обеспечиваемых устройствами ввода/вы- вода. Поэтому для записи конструкций, лежащих даже на нижнем уровне иерархии (см. рис 7 1), используются не отдельные литеры, а цепочки литер, называемые лек- семами. При этом символы, образующие лексему, теряют свою индивидуальность' смысловое значение, приписываемое этой строке семантикой, не вытекает из смы- словых значений составляющих ее символов. Текст программы можно рассматривать как цепочку в алфавите лексем. Такая цепоч- ка получила название лексической свертки программы.
530 Часть II. Применение графов и граф-моделей Разные языки различаются наборами лексем. Вместе с тем большинство языков про- граммирования содержит следующие группы (типы) лексем: идентификаторы, сим- волы операций, служебные слова, шумовые слова. Идентификаторами обычно называют лексемы, состоящие из букв и цифр и начи- нающиеся с буквы. В разных языках допускаются следующие вариации этого (син- таксического) правила: определяется ограничение на длину цепочки (например, в Фортране длина идентификатора не превышает шести), разрешается включать в идентификаторы специальные литеры, такие как (точка) или "—" (тире), или запрещается использовать в качестве идентификаторов определенные слова, назы- ваемые ключевыми или зарезервированными (например, VAR, DIV или FOR в языке Паскаль. Для обозначения операций в большинстве языков используются отдельные специаль- ные литеры (например,"+" или "-") или их цепочки (например, " * *" или ":="), назы- ваемые символами (или знаками) операций. В каждом языке программирования имеется набор служебных слов— лексем, ис- пользуемых в качестве фиксированных частей в синтаксисе понятий. В качестве та- ких лексем используются либо отдельные литеры (например, (, [, begin или for в Алголе-60), либо идентификаторы специального вида (например, IF или DO в Фор- тране), либо ключевые слова (например, IF или то в Паскале). Большинство языков предусматривает возможность включать различного рода шумо- вые или необязательные слова, которые игнорируются исполняющей машиной. Ино- гда они определяются явно (например, в Паскале комментариями являются последо- вательности символов, содержащие специальные ограничители) или неявно, через контекст (например, в Алголе-60 любая последовательность, лежащая между симво- лами end и и не содержащая этих символов, рассматривается в качестве коммен- тария). Во многих языках используются комбинированные правила задания шумовых слов (например, в языке Фортран пробелы существенны только в строках). В некоторых языках требуется размещение шумовых слов между определенными видами лексем (например, в Паскале между идентификатором и ключевым словом должен находиться хотя бы один символ конца строки, комментарий как пробел). Ряд языков предполагает полную или частичную (как в Фортране) фиксацию правил вхо- ждения лексем в части текста программы между символами "конец строки", разби- вающих текст программы на строки (образы перфокарт). Иногда особое значение имеет первая литера, расположенная сразу за символом "конец строки". Для записи более сложных конструкций языка используются понятия, такие как, на- пример, "арифметическое выражение" или "оператор присваивания". Понятиями называют такие элементы языка, каждому вхождению которых в про- грамму правила языка однозначно сопоставляют его синтаксическое значение— не- которую цепочку в алфавите лексем При этом одному и тому же понятию, как пра- вило, соответствует множество значений вхождений, а для любых двух вхождений понятий их значения либо не имеют общих подцепочек лексической свертки про- граммы (независимость), либо одно значение входит полностью в другое (включе- ние) Например, большинство языков в строке А * В + С выделяет три идентификато-
Глава 7. Синтаксические деревья 531 ра разделенных двумя знаками операций, и два вхождения понятия "арифметическое выражение" со значениями А*ВиА*В + С. Лексемы и понятия называются грамматическими элементами языка. Правила языка задают не только допустимые отношения между грамматическими элементами (их вхождениями в тексты программ), но и приписывают каждому грамматическому эле- менту набор характеристик, называемых атрибутами. Атрибуты отражают общность и различие семантических объектов, обозначаемых всевозможными вхождениями данного грамматического элемента. Каждый атрибут характеризуется областью его значений, являющихся атрибутами вхождений соответствующего грамматического элемента. Структура вхождения грамматического элемента вместе с его атрибутами и атрибутами всех составляющих его вхождений грамматических элементов однознач- но определяет семантический объект, обозначаемый данным вхождением. Отношения независимости и включения между синтаксическими значениями вхож- дений понятий, естественно, переносятся и на сами вхождения, и таким образом каж- дое вхождение понятия в программу представляет собой некоторую иерархию вхож- дений понятий и лексем. В отличие от лексем смысловое значение некоторого вхождения понятия образуется из смысловых значений составляющих его вхождений понятий и лексем. Наиболее важным из атрибутов, характеризующих в языке семантический объект, является его класс, т. е. информация о том, является ли данный объект операцией, оператором и т. д. В свою очередь в своем классе семантические объекты могут раз- личаться по значениям других (своих собственных) атрибутов, например, данные в языке (элементы памяти исполняющей машины) делятся на константы, значения которых постоянно, и переменные; переменные различаются своими именами (адре- сами) и типами (множествами допустимых значений); операции различаются по их именам (кодам в исполняющей машине), а также по типу, т. е. по числу и типам опе- рандов и по типу результата. Следует отметить, что не всегда удается полностью зафиксировать для языка на этапе его определения все атрибуты, часть значений атрибутов полностью уточняются лишь на этапе реализации языка. Определение арифметических операций и представ- лений чисел — очевидные примеры. В большинстве языков высокого уровня стре- мятся минимизировать такую зависимость от реализации, чтобы достичь большей мобильности программ. Процесс сопоставления вхождениям лексем и понятий в программу совокупностей значений их атрибутов называется связыванием. Определение языка для каждой про- граммы задает правила связывания, задающие те моменты выполнения программы на исполняющей машине, при которых осуществляется та или иная связь, а также те, при которых она нарушается (тем самым выделяются те временные интервалы рабо- ты исполняющей машины, когда существует данная связь). Обычно момент наруше- ния связи — это момент установления новой связи. Часть связываний осуществляется при определении языка. Например, для ряда лек- сем в определении языка фиксируется их класс, для многих знаков операций — их тип и т. д. Однако большинство связываний происходит при выполнении программы.
532 Часть II. Применение графов и граф-моделей 7.1.2. Схема процесса трансляции Переработка текста входной программы в эквивалентную последовательность ма- шинных команд явно не является простым действием, чтобы с логической или реали- зационной точки зрения его рассматривать как одношаговый процесс. С логической точки зрения процесс естественно разделяется на четыре логически обособленные части — так называемые этапы трансляции, выделение которых дает представить перевод программы с входного языка на выходной в виде последова- тельного выполнения этапов лексического, синтаксического и контекстного анализов и генерации. Реализация процесса трансляции в виде последовательности шагов предполагает раз- биение транслятора на части (обычно называемые просмотрами) таким образом, что каждый просмотр воспринимает представление транслируемой программы, вырабо- танное на предыдущем просмотре или являющееся входным для всего транслятора (в случае первого просмотра), и создает новое представление программы, которое является либо входным для следующего просмотра, либо результатом работы всего транслятора, если просмотр был последним Рис. 7.2. Принципиальна схема процесса трансляции Схемой процесса трансляции называется схема организации и взаимодействия про- смотров с распределением по просмотрам функций этапов трансляции. В качестве реализации процесса трансляции можно представить такую схему этого процесса, при котором каждый этап — в соответствии с принципиальной схемой,
Гпава 7. Синтаксические деревья 533 приведенной на рис. 7.2, выполняется независимым просмотром (или последователь- ностью просмотров). Первые три этапа осуществляют извлечение абстрактной программы из исходного текста: вначале лексический анализ производит построение по тексту исходной про- граммы ее лексической свертки; затем лексическая свертка преобразуется синтакси- ческим анализом в дерево разбора; и наконец, вершинам этого дерева на этапе кон- текстного анализа приписываются значения всех так называемых статических атри- бутов. Атрибуты абстрактной программы кодируют ту часть синтаксических свойств транслируемой программы, которые не описываются КС грамматикой (например, такой атрибут, как класс конструкции, связанной с идентификатором), а также ряд других (семантических) ее свойств, позволяющих осуществлять построение выход- ной программы (на этапе генерации) при систематическом обходе дерева разбора и за счет вызовов генерационных процедур (трансдукторов), обрабатывающих вершины дерева вместе с их атрибутами и соответствующих понятиям и лексемам языка. Для конкретного языка реализация принципиальной схемы трансляции, однако, не является достаточно эффективной, т. к. заведомо возможно хотя бы частичное объ- единение функций различных этапов на одном просмотре, что дает возможность предложить более эффективные схемы процесса трансляции. Поэтому на практике встречаются одно-, двух- и многопросмотровые схемы процесса трансляции. Основ- ной является двухпросмотровая схема; она приемлема для большинства входных языков и достаточно проста и эффективна. Однопросмотровые схемы, в которых все этапы объединены в одном просмотре, для большинства языков не удается реализовать из-за невозможности совмещения в од- ном просмотре для этих языков выполнения идентификации и семантической индук- ции, составляющих контекстный анализ. Многопросмотровые (при числе просмотров больше двух) схемы трансляции, как правило, требуются для таких языков, как, на- пример, Алгол-68, в которых синтаксическое определение существенно связано с контекстными условиями, и позволяют включать в процесс трансляции дополнитель- ные функции (например, оптимизацию транслируемой программы). Ресурсы ЭВМ, выделяемые транслятору, также могут влиять на число просмотров в нем. Например, многопросмотровая схема позволяет реализовать транслятор, предъявляющий мень- шие запросы к оперативной памяти, чем однопросмотровые, поскольку разные про- смотры не обязаны храниться одновременно в оперативной памяти и могут сменять друг друга на одном и том же ее участке. 7.1.3. Лексический, синтаксический и контекстный анализ Входом транслятора является длинная цепочка, анализ которой транслятор должен проводить литера за литерой, несмотря на то, что с точки зрения вида абстрактной программы представляются совершенно несущественными кодировки, используемые для записи разных лексем языка. Первый шаг, который должен выполнить трансля- тор,— это преобразовать исходную цепочку в последовательность внутренних коди-
534 Часть II. Применение графов и граф-моделей ровок, образующих так называемую лексическую свертку входной программы, и на- бор таблиц лексем. В лексической свертке каждая лексема приводится к единому формату и представляется посредством дескриптора, содержащего два вида инфор- мации: тип (или класс) лексемы как синтаксической единицы (идентификатор, слу- жебное слово и т. п.), а также местоположение данной конкретной лексемы (вход в таблицу идентификаторов, номер в таблице служебных слов и т. п.). Синтаксис лек- сем описывается в рамках наиболее простых автоматных грамматик, тем не менее этот этап трансляции часто занимает больше времени, чем любой другой из-за необ- ходимости политерной обработки входной строки и разбиения ее на вхождения под- строк из практически неограниченного множества. Выходом лексического анализа является лексическая свертка транслируемой про- граммы. Следующим шагом трансляции является этап синтаксического анализа, или разбора, осуществляющий выявление в лексической свертке программы структуры вхождений лексем и понятий и проверку, удовлетворяет ли эта структура синтаксису языка Синтаксическая структура программы показывает существующие в ней связи между соответствующими частями и тем самым помогает вскрывать смысл програм- мы. Так, рассматривая арифметическое выражение А + В * С в языке Паскаль и отме- чая скобками вхождения понятий, мы приходим к его структуре (А + (В * С)), в кото- рой явно показывается, какие части арифметического выражения связаны знаком плюс, а какие — знаком умножения. Если бы соответствующая структура имела бы вид ((А + В) * С), то арифметическое выражение имело бы совершенно другой смысл (семантику). Обычно предполагается, что выявляемые при синтаксическом анализе структуры описываются с помощью некоторой КС-грамматики, нетерминальными символами которой являются понятия языка, а терминальными— отдельные лексемы (напри- мер, служебное слово begin в языке Паскаль) и типы лексем (например, такой тип лексем, как идентификатор). Результатом синтаксического анализа служит построе- ние дерева разбора транслируемой программы. Завершающим этапом в построении абстрактной программы по исходному тексту является этап контекстного анализа, которому посвящена гл. 8. Выходом синтаксиче- ского анализа является представление программы в виде дерева разбора, описываю- щего иерархическое строение составляющих ее вхождений понятий и лексем. Про- цесс дальнейшей трансляции связан с систематическим обходом этого представления программы, порождающим строку на выходном языке. При этом предполагается, что результат обработки (перевод) некоторого вхождения понятия полностью определя- ется непосредственными связями корня поддерева, соответствующего этому вхожде- нию понятия, и переводами его составляющих вхождений, причем непосредственные связи в дереве рассматриваются либо по предшествованию, либо по следованию. Та- кая локальность перевода достигается за счет снабжения атрибутами вершин дерева разбора программы. В атрибутном дереве программы вершины соответствуют тем же понятиям, что были выделены в дереве разбора, но снабжены дополнительной информацией о тех свойствах (атрибутах) соответствующих вхождений понятий или лексем, в которых учитывается не только синтаксическое строение, но и контекст данного его вхождения.
Гпава 7. Синтаксические деревья 535 Исходя из КС-грамматики (см. разд. 7 2) и определяемого ей дерева разбора для дан- ной программы, мы можем судить в основном об иерархических отношениях между вхождениями понятий, а большая часть их свойств, определяющая семантическое соответствие текстов, сопоставленных вхождению понятия во входной и выходной строках, — то соответствие, достижение которого есть задача трансляции, может быть обнаружено только на основании учета контекста данного вхождения. Необходимость учета контекста для построения выходной строки может быть проде- монстрирована хотя бы на таком простом примере. Рассматривая фрагмент исходно- го текста программы х := Y;", мы на основании КС-грамматики (например, для языка Паскаль) обнаружим, что имеем дело с оператором присваивания, левая и пра- вая части которого состоят из индентификаторов. Эта информация еще не дает нам однозначных ответов на следующие вопросы: можно ли реализовать этот оператор приданием переменной X значения, совпадающего с текущим значением переменной Y, или для получения нужного значения X требуется его вычисление в соответствии с описанием процедуры без параметров У, совпадают ли типы переменных X и У или значение переменной У должно быть предварительно преобразовано к типу перемен- ной X— перечень возможных вариантов можно продолжить, допустив, например, что либо X, либо У является формальным параметром. 7.2. Порождающие грамматики Даже с синтаксической точки зрения язык программирования — это не просто мно- жество текстов, записанных с помощью некоторого набора символов— алфавита языка. Важным при определении языка программирования является описание тех синтаксических структур, которые приписываются языком каждому из этих текстов (предложений). Порождающие грамматики, широко используемой формой записи которых является БНФ, позволяют задавать не только множество предложений языка программирования, но и их синтаксическую структуру. 7.2.1. Цепочки и языки Алфавит есть любое конечное множество символов, называемых буквами (или зна- ками алфавита). Если написать последовательность символов, располагая их один за другим, то получается цепочка (а также слово или строка) символов. Например, 001111 — цепочка в бинарном алфавите {0,1}. Через е будет обозначаться пустая цепочка, т. е. цепочка, которая не содержит ни одного символа. Е* обозначает множе- ство всех цепочек в алфавите Е, включая е, а Е = Е* - {е}. Длина цепочки х (обозна- чаем | х |) — это число символов в ней Выделяются две операции над цепочками. Если х и у— две цепочки, то цепочка ху называется конкатенацией (или сцеплением) х и у. Например, для любой цепочки х всегда хе = ех = х. Обращением цепочки х называется цепочка х, записанная в обрат- ном порядке. Для любого символа а через ак обозначается его А-кратная конкатенация (например, I3 обозначает цепочку 111).
536 Часть II. Применение графов и граф-моделей Пусть х, у и z — произвольные цепочки в некотором алфавите Е. Цепочка х называет- ся префиксом цепочки ху, z— подцепочкой цепочки xzy, ay— суффиксом цепочки ху, в частности, пустая цепочка является префиксом, суффиксом и подцепочкой лю- бой цепочки. Еслих Фу их— префикс (суффикс) цепочки у, тох называется собст- венным префиксом (соответственно суффиксом) цепочки у. Языком в алфавите X называется любое подмножество множества X*. Так как язык — подмножество, операции объединения, пересечения, нахождения разности и допол- нения применимы и к языкам. Кроме этих операций над языками рассматривают еще операции конкатенации, итерации и позитивной итерации. Пусть L\ — язык в алфавите L2— язык в алфавите Е2. Тогда язык, состоящий из всех таких цепочек ху, что хе L\ и у е L2, называется конкатенацией (а также сцеп- лением, или произведением) языков L\ и L2 и обозначается через L}L2. Для любого неотрицательного к определена ^-итерация языка L, обозначаемая через Lk, по следующим правилам: □ L°= {е}; П Lk - LLk~' для любого к > 1. Позитивная итерация языка L, обозначаемая через L+, — это язык, получаемый объ- единением языков Lk для всех к > 1; £' = Г и £с называется итерацией языка. 7.2.2. Грамматики составляющих Под (порождающей) грамматикой понимается четверка Г = (И, W, Е, Р), в которой: ПК — алфавит терминальных символов, или терминалов (тех символов, которые можно использовать для записи предложений языка); □ IV— непересекающийся с V алфавит нетерминальных символов, или нетермина- лов (иногда называемых вспомогательными символами, металингвистическими или синтаксическими переменными)', □ Е — выделенный символ из W, называемый начальным символом (или аксиомой); ПР — множество правил (или продукций), имеющих вид а—> Р, где а и р — различ- ные цепочки в алфавите Ги Е, а >" — символ, не входящий в Ки W. Заметим, что мы ограничиваемся рассмотрением только класса порождающих грам- матик, предложенных Н. Хомским и получившим название грамматик Хомского (или грамматик составляющих). Примером грамматики служит четверка Г1 = ({0,1}, {ШКАЛА, БИТ, £}, Е, Р), в которой Р состоит из правил: Е БИТ ШКАЛА, ШКАЛА БИТ ШКАЛА,
Гпава 7. Синтаксические деревья 537 ШКАЛА->е, БИТ -» О, БИТ —> 1. Нетерминальными символами являются Е, БИТ и ШКАЛА, а терминалами — 0 и 1. Грамматика Г для любой цепочки ю = а[3у задает множество выводимых из нее цепо- чек. Это множество рекурсивно можно определить следующим образом: П если р~> о содержится в Р, то цепочка т = ару непосредственно выводима из со (обозначается со => т); П если г] выводима из со и р => т, то т нетривиально выводима из со (обозначается со =>+ т); П если со => т или со = т, то т выводима из со (обозначается со =>*т). Последовательность цепочек а1; аг,..., а*, в которой каждая последующая цепочка непосредственно выводима из предыдущей, т. е. aj => аг => ...=> а*, называется выводом цепочки а, если а! = Е, а* = а. Цепочка, выводимая из £, называется сентенциальной формой. Сентенциальная фор- ма, не содержащая нетерминалов, называется предложением. Множество предложе- ний образует язык, порожденный грамматикой Г (обозначается £(Г)). Для нашего примера грамматики Г! существует вывод цепочки 1, поскольку Е => БИТ ШКАЛА => 1 ШКАЛА => 1. Таким образом, Е => 1, Е =>* 1 и цепочка 1 принадлежит языку Л(Г). Можно прове- рить, что £(Г) содержит все непустые цепочки в алфавите {0, 1}. В дальнейшем для обозначения к правил а-» рь а—» р2, а—> р* будет использоваться запись а-» Pi | Рг |... | Р*. Грамматики можно классифицировать по виду их правил. Пусть Г = (И, W, Е, Р) — некоторая грамматика. Грамматика Г называется грамматикой: П типа 3 {автоматной грамматикой), если каждое правило из Р имеет вид А —> хВ или А —>х, гдех е V, {А, В} с W\ □ типа 2 {контекстно-свободной или А'С-грамматикой), если каждое правило из Р имеет вид А —> а, где А е W, а а — цепочка в алфавите Ги W;
538 Часть II. Применение графов и граф-моделей □ типа 1 (контекстно-зависимой или неукорачивающейся грамматикой), если каж- дое правило из Р имеет вид ct-> Р, где длина цепочки а не превышает длины це- почки Р; □ типа 0 (грамматикой составляющих или с фразовой структурой) в общем случае. Указанные четыре типа грамматик и языков, связанных с соответствующими типами грамматик, часто называют иерархией Хомского. А. Для любого КС-языка L существуют такие целые числа I и к, что любая цепочка а е L длины ]сс| > / представима в виде а = uvaxy, где цепочки и, v, со, х и у удовле- творяют следующим свойствам: П | vcox| < к; П не пуста цепочка vx' П иг'сох'у е L для всех I > 0. Б. L является контекстно-зависимым языком тогда и только тогда, когда сущест- вует грамматика G = (V,W, Е, Р), в которой каждое правило имеет вид а/ф—>сссор, где Леф сое(К u W)*, ар е (Ии IV)+. В. Для любого автоматного языка L существует такое целое к, что любая цепочка со е L длины |со| > к представима в виде со = хуг, для некоторых таких цепочек x,yuz, что 0 < [р| < А и xy'z е L для всех i > 0. Автоматные языки описываются наиболее простым классом грамматик, и алгоритм распознавания их чрезвычайно прост. Автоматные грамматики используются при трансляции, главным образом, при предварительном преобразовании программ с целью их представления в форме, более удобной для дальнейшей обработки. Пусть Е некоторый алфавит. Регулярные множества в Е определяются по следую- щим правилам: П пустое множество, множество из одной пустой цепочки, а также множество из одной цепочки а для любого аеЕ являются регулярными множествами; П если Q и Р— регулярные множества, то регулярными множествами являются также множества P\j Q, PQ и Р . Г. L является регулярным множеством тогда и только тогда, когда L является автоматным языком. 7.2.3. Контекстно-свободные языки Из четырех классов грамматик Хомского наиболее важным с точки зрения приложе- ний к языкам программирования является класс КС-грамматик (см. разд. 7.2.2). Это связано с тем, что средствами КС-грамматик удается достаточно полно описать син- таксические структуры существующих языков программирования, и имеются доста- точно хорошо разработанные алгоритмы распознавания КС-языков, которые состав- ляют важную часть транслятора — этап синтаксического анализа. Под распознавани-
Глава 7. Синтаксические деревья 539 ем КС-языка понимается распознавание принадлежности любой цепочки к данному КС-языку и в случае обнаружения этой принадлежности — определение ее синтакси- ческой структуры. КС-грамматики обладают свойством локальности и независимости подстановок в том смысле, что подстановка, выполняемая в некоторой области (подцепочке) данной цепочки, никак не зависит от подстановок, выполняемых вне этой области, а резуль- таты подстановки остаются внутри той же области. Это позволяет построение пред- ложений и их анализ разбивать на подчасти, не зависимые друг от друга, что также приводит к существованию эквивалентных выводов в КС-грамматиках в том смысле, что во всех них применяются одни и те же правила в одних и тех же местах, но в раз- личном порядке. Применение к цепочке правил подстановки, по существу, является двумерным про- цессом из-за независимости порядка выполнения подстановок в различных частях цепочки, поэтому удобно использование графического представления класса всех эквивалентных выводов, называемого деревом вывода (или деревом разбора, когда все висячие вершины дерева помечены терминалами и символом е). Дерево вывода в КС-грамматике— это помеченное упорядоченное дерево, удовле- творяющее следующим двум свойствам: П вершины дерева помечены символами из V vj {е}, причем корень дерева по- мечен символом £; П для любой внутренней вершины q0 дерева и списка ее сыновей ,qu q2, qr, пере- численных в порядке их упорядоченности, множество правил грамматики Р со- держит такое правило А —> at а2 ... ап что A, at, а2, ..., аг являются пометками вер- шин q0, qt, q2,..., qr соответственно. В качестве примера рассмотрим грамматику ({а, +, *, (,)}, {F, Е, Т}, Е, /’), в которой Р состоит из следующих правил: £—>£+7’| 7; Т^> Т* £| £; F->(£)|a. Примеры двух эквивалентных выводов в этой грамматике: Е=>Е+Т=> Т+Т=>Т+Т*Е; Е=> Е+ Т=> Е+ Т* F=>T+T* F. Эти эквивалентные выводы цепочки Т + Т * F представляются в виде дерева вывода, изображенного на рис. 7.3. В данном и следующих примерах упорядочение сыновей вершин отражается их расположением слева направо. Грамматика, рассмотренная в данном примере, не раз еще будет использоваться при дальнейшем изложении; мы всегда будем обозначать ее через Го. Поскольку любое дерево вывода является упорядоченным, для его висячих вершин существует единственное линейное упорядочение. Выписывая пометки висячих вер-
540 Часть II. Применение графов и граф-моделей шин в этой упорядоченности, можно получить цепочку, выводы которой представле- ны этим деревом. Такую цепочку называют кроной дерева. Часть кроны дерева, яв- ляющаяся кроной некоторого его поддерева, называется фразой. Основа — это самая левая фраза, не содержащая других (не совпадающих с ней) фраз. Например, изобра- женное дерево вывода в грамматике Го (см. рис. 7.3) имеет три фразы: Т, Т* F и Т + Т * F, из которых фраза Т является основой. Среди множества эквивалентных выводов одной и той же цепочки обычно выделяют так называемые правый и левый выводы. Вывод а, => а2 => .. => а, является левым (соответственно правым}, если для любого / цепочка а,,, получается из а, применени- ем правила к ее самому левому (соответственно к самому правому) вхождению не- терминала левой (соответственно правой) подстановкой. Широко используемой формой записи правил КС-грамматик является форма Бэку- са—Наура (БНФ). В ней вместо символа —> используется символ ::=, а металингви- стические переменные представляют собой слова или группы русских (или других) слов, заключенные в специальные кавычки < >, такие как, например, <программа> или <арифметическое выражением Правила грамматики, записанные в БНФ, обычно называются (металингвистическими) формулами. В последнее время все большее паспространение получают различные расширения БНФ (например, часто в правой части формулы допускают задание регулярного выражения) или ее модификации (на- пример, в качестве металингвистических переменных рассматриваются слова, со- стоящие из русских строчных букв и дефисов). 7.2.4. Эквивалентные преобразования грамматик С разных точек зрения может оказаться желательным преобразование заданной грамматики в такую эквивалентную ей грамматику (эквивалентную в том смысле, что она порождает тот же язык, что и исходная грамматика), которая удовлетворяет оп- ределенным свойствам (заметим, что нет общего алгоритмического метода, осущест- вляющего любую желаемую модификацию грамматики). Например, может возник- нуть необходимость исключить так называемую левую рекурсию или удалить все правила с пустой правой частью.
Гпава 7. Синтаксические деревья 541 Однако для достижения той или иной цели не всякое эквивалентное преобразование грамматики будет допустимым, поскольку приходится заботиться о сохранении ряда свойств исходной грамматики. Например, переход от грамматики Го к эквивалентной грамматике, содержащей несколько другой набор правил Е^>Е+Т\Е* Г| Г, Т^>(Е) а, нельзя признать допустимым, поскольку после такой модификации структура выра- жений а+ а* аиа* а + а подразумевает тот же порядок выполнения операций, что и в выражениях (а + а) * а и (а * а) + а соответственно. Одним из важных свойств грамматики с точки зрения трансляции является ее одно- значность, означающая то, что не существует предложения, являющегося кроной двух или более деревьев вывода в данной грамматике. Свойство однозначности грамматики может быть нарушено в результате эквивалентного преобразования. На- пример, для однозначной грамматики Го эквивалентной является неоднозначная грамматика, имеющая следующий набор правил: Е^>Е + Е\ Е*Е \ (Е) | а. Действи- тельно, для выражения а + а * а можно построить два разных дерева вывода (рис. 7.4). Содержательно это означает следующее: нельзя сказать, что выполняется в выражении а + а * а раньше— умножение или сложение. Преобразование, нару- шающее однозначность грамматики, почти всегда будет недопустимым. Рис. 7.4. Два разных дерева вывода цепочки а + а * а Неоднозначность грамматики нельзя путать с неоднозначностью языка, порождаемо- го грамматикой. Язык неоднозначен, если его нельзя породить ни одной однозначной грамматикой. Таков, например, язык, состоящий из всех цепочек a" b‘” ск, в которых либо и = т, либо от = к. Существуют преобразования, являющиеся эквивалентными для любой КС- грамматики и всегда допустимые. Они связаны с добавлением или удалением так на- зываемых бесполезных символов. Это такие символы, которые либо не появляются ни в одной сентенциальной форме, либо не могут порождать терминальных цепочек и, таким образом, не участвуют в порождении предложений языка в данной грамма- тике. Ясно, что при описании синтаксиса реальных языков программирования не ис- пользуются грамматики с бесполезными символами. Кроме того, существует доста- точно простой алгоритм определения для любой КС-грамматики всех ее бесполезных символов. Он позволяет по любой КС-грамматике строить эквивалентную ей приве- денную (без бесполезных символов) грамматику.
542 Часть II. Применение графов и граф-моделей В качестве допустимых обычно используются также следующие эквивалентные пре- образования грамматик. Подстановка правил. Данное преобразование осуществляет некоторую такую экви- валентную модификацию грамматик, при которой добавляется новое правило А -> а, где а выводимо из А в исходной грамматике, а также удаляются некоторые правила, участвующие в выводах А =>+ а. В своем простейшем виде подстановка правил озна- чает замену некоторого правила А -> аВ Р множеством правил А -> ay, р для всех таких у, что В у — правило исходной грамматики (например, подстановка в прави- ло £ —> сЕаЕ преобразует грамматику Е —> сЕаЕ\В в грамматику Е —> cEab | сЕасЕаЕ | Ь либо в грамматику Е —> cbaE | ссЕаЕаЕ\Ь). Следует заметить, что в результате под- становки символ В может стать бесполезным. Добавление нетерминала. В своем простейшем виде означает замену некоторого пра- вила А аРу на два правила: А —> А аРу и В -> р, где В не входит в исходную грам- матику. Нетрудно заметить, что, осуществляя добавление относительно нескольких правил А —> о.Р| у|...| Лар., у, мы как бы склеиваем эти правила в одно, получая А ->ару мВ-> р,|... |р.,.. Изменение направления рекурсии. Пусть исходная грамматика не содержит символа В и пусть а aat | Ла21 ... | Aak | Pi | Р2 | - | Р., — все ее правила, у которых А является левой частью, причем ни одна из цепочек р, не начинается с А. Тогда изменение на- правления рекурсии состоит в замене указанных правил на правила а р, I р21... I P.d Р.в I р2Д| -1 Р,в; В -> а| | а21... | ак | а}В | а2В | ...| акВ. Например, в результате изменения направления рекурсии можно преобразовать грамматику Го в эквивалентную ей грамматику Г2 с правилами £—>7’| ТЕ'; £'->+7’| + ТЕ'; T^>F\FT'; Т'->* F\* FT'; F—>(E)\a. Рассмотренный набор допустимых преобразований является достаточно мощным и в большинстве реальных ситуаций позволяет получать грамматики, обладающие нужным набором свойств. В частности, он позволяет переходить к следующим под- классам КС-грамматикам, свойства которых позволяют решать задачи трансляции более эффективно. Грамматика без е-правил. Это означает, что либо грамматика совсем не содержит правил вида А е, либо в ней имеется ровно одно правило с пустой цепочкой в пра- вой части £ —> е, но £ не встречается в правых частях остальных правил грамматики. Грамматика без цепных правил — в ней нет правил вида А —> В. Грамматика без циклов — в ней нет выводов А А.
Глава 7. Синтаксические деревья 543 Нормальная форма Хомского, когда грамматика является грамматикой без е-прав ил и каждое ее правило, отличное от Е —> е, имеет вид А —> ВС или А —> а для некоторого терминала а и нетерминалов В и С. Грамматика без левой рекурсии — в ней нет выводов А => А а. Нормальная форма Грейбах. Грамматика является грамматикой без е-правил и каж- дое ее правило, отличное от Е —> е, имеет вид А —> «а, где а — некоторый терминал, а а — цепочка, состоящая из нетерминалов. 7.3. Лексический анализ Обычно первым этапом процесса трансляции является лексический анализ, задача которого состоит в получении строки, представляющей собой лексическую свертку исходной программы. Эта строка в алфавите лексем образует вход синтаксического анализа — этапа трансляции, осуществляющего построение дерева разбора. Лексический анализатор является промежуточным звеном между внешним миром и другими частями транслятора; одинаковые программы, имеющие разные внешние представления, после прохождения через этап лексического анализа становятся иден- тичными с точки зрения остальных частей транслятора. 7.3.1. Распознаватели Врезе). 7.1.1 уже упоминался метод задания языка программирования с помощью распоз навагеле й. Распознаватель состоит из трех частей: входной ленты, управляющего устройства с конечной памятью и вспомогательной (или рабочей) памяти. Входная лента — это потенциально неограниченная в обе стороны линейная после- довательность клеток или ячеек, каждая из которых содержит либо пустой символ (пробел), либо символ из некоторого входного алфавита. Входная головка в каждый момент обозревает одну входную ячейку. За один такт работы распознавателя вход- ная головка может сдвинуться на одну ячейку влево, остаться неподвижной или сдви- нуться вправо. Мы будем рассматривать только односторонние распознаватели, входная головка которых никогда не передвигается влево, а также предполагать, что входная головка только читает, т. е. в ходе работы распознавателя состояние входной ленты не меня- ется. Примером распознавателя, не удовлетворяющего этим условиям, является ма- шина Тьюринга. Существуют распознаватели с различными типами вспомогательной памяти, в ячей- ках которой хранятся символы из некоторого внутреннего алфавита, и ее тип обычно и определяет тип распознавателя. Мы будем рассматривать конечные автоматы, у которых вспомогательная память вообще отсутствует, а также автоматы с магазин- ной памятью (или МП-автоматы), вспомогательная память которых организована по принципу магазина.
544 Часть II. Применение графов и граф-моделей Управляющее устройство распознавателя состоит из конечного множества внутрен- них состояний, среди которых выделено начальное состояние и множество заключи- тельных состояний, а также управляющего отображения, которое описывает, в какое перейти внутреннее состояние, какую информацию поместить в рабочую память и как изменить положение входной головки в соответствии с обозреваемым символом, текущим состоянием и информацией, извлеченной из рабочей памяти. Конфигурация распознавателя— это состояние управляющего устройства; неис- пользованная часть входной цепочки, самый левый символ, который обозревается входной головкой; а также содержимое памяти. Среди множества всех конфигураций выделяются множества начальных и заключительных конфигураций. В начальной конфигурации входная цепочка записана на входной ленте и ограничена с обеих сто- рон пробелами, входная головка обозревает самый левый символ входной цепочки, управляющее устройство находится в начальном состоянии, а внутренняя память имеет заранее установленное начальное содержимое. В заключительной конфигура- ции входная головка обозревает ячейку, расположенную справа от входной цепочки, управляющее устройство находится в одном из заключительных состояний, а внут- ренняя память удовлетворяет некоторым заключительным условиям. Распознаватель работает, проделывая некоторую последовательность шагов (или так- тов) и переходя от одной конфигурации к другой в соответствии с управляющим ото- бражением. При этом распознаватель называется детерминированным, если для каж- дой конфигурации существует не более одного допустимого шага, и недетерминиро- ванным, если таких шагов может быть несколько. Говорят, что распознаватель допускает входную цепочку а, если, начиная с началь- ной конфигурации, в которой а записана на входной ленте, он может проделать по- следовательность шагов в соответствии с управляющим отображением, которая за- канчивается заключительной конфигурацией. Язык, определяемый распознавате- лем, — это множество всех цепочек, которые он допускает. В практике трансляции рассматриваются распознаватели с выходами (или преобра- зователи), которые дополняются выходной лентой и на каждом шаге распознавания могут выдавать на выходную ленту цепочку выходных символов ограниченной длины. Наиболее простым и изученным классом распознавателей являются конечные авто- маты. Эти распознаватели не имеют рабочей памяти, причем обычно предполагает- ся, что конечный автомат после прочтения некоторого входного символа всегда пе- редвигает входную головку вправо. Таким образом, отношение, управляющее функ- ционированием этого распознавателя, определяет для каждой пары (входной символ, состояние) множество состояний, в которых автомат может находиться на следую- щем шаге. Это отношение для конечного автомата называется функцией перехода. Существуют различные варианты определения конечного автомата, связанные с раз- личными способами задания функции перехода. Например, для автомата, допускающего язык всех цепочек вида а'Ь", где тип — произвольные положительные целые числа, задание функции перехода в виде после- довательности команд будет иметь вид:
Глава 7. Синтаксические деревья 545 (fl, Ад) —» {^41} (fl,Ai)—> Mi} (Ь,А\)—> {А2} (Ь, А2) —> {А2} (В, А2)—> {А3} Здесь {а, Ь} — внешний алфавит, {Ло, А}, А2, А3} — алфавит внутренних состояний, Ае— начальное состояние, {А3}— множество заключительных состояний. В этом примере и дальше пустой символ обозначается через В. Отсутствие в наборе команд команды, левой частью которой является пара (б, /10), означает, что значением функ- ции перехода на (Ь, Ад) является пустое множество. Итак, если автомат в состоянии Ао обозревает символ Ь, то он останавливается. Сопоставив каждому состоянию некоторую вершину, а каждой команде (а, А) —> {С} — дугу, помеченную символом а и ведущую из вершины с пометкой А в вершину с по- меткой С, можно представить конечный автомат в виде помеченного ориентирован- ного мультиграфа, называемого диаграммой переходов. Например, описанному авто- мату отвечает граф, изображенный на рис. 7.5, а. Этот граф может быть задан в виде так называемой матрицы переходов (рис. 7.5, б). В качестве примера недетерминированного автомата рассмотрим автомат, допус- кающий все цепочки в алфавите {а, Ь}, у которых последний символ цепочки входит в цепочку как минимум дважды (например, цепочка aba допускается, а цепочка aaab— нет). Граф переходов этого автомата приведен на рис. 7.6, а. Здесь А — на- чальное состояние, {/С} — множество заключительных состояний. Этот автомат не- детерминированный, поскольку, например, обозревая символ а и находясь в состоя- нии D, автомат может перейти в каждое из двух состояний Dm К. Рис. 7.5. Представления конечного автомата в виде: а — диаграммы переходов, б — матрицы переходов 18 Зак. 202
546 Часть II. Применение графов и граф-моделей Хотя на первый взгляд недетерминированный конечный автомат располагает боль- шими возможностями, класс языков, допускаемых обоими типами автоматов, оказы- вается одинаковым и совпадает с классом языков, порожденных грамматиками ти- па 3. Например, для указанного недетерминированного конечного автомата детерми- нированный автомат, допускающий тот же язык, может иметь вид, изображенный на рис. 7.6, б (заметим, что в нем состояниями являются подмножества множеств со- стояний исходного недетерминированного автомата— возникли новые состояния CD, DE, СЕ и СОЕ). Рис. 7.6. Детерминизация конечного автомата: а — исходный недетерминированный конечный автомат, б — результирующий детерминированный конечный автомат Внимательное сопоставление этих двух автоматов (см. рис. 7.6) позволяет понять алгоритм перехода от произвольного недетерминированного конечного автомата к допускающему тот же язык детерминированному. В частности, в детерминированном автомате существует команда (fl, $,)-►{&} тогда и только тогда, когда в недетерминированном автомате существует команда (а, Л,)-> {Л2} для некоторых Л । е и^2 g S2. 7.3.2. Функции лексического анализа Синтаксис лексем можно описать в рамках наиболее простых автоматных грамматик. Таким образом, лексический анализатор (или сканер)— это детерминированный конечный преобразователь (конечный автомат с выходом), входом которого служит
Глава 7. Синтаксические деревья 547 цепочка символов, представляющая исходную программу, а выходом — последова- тельность лексем, образующих собственно лексическую свертку исходной програм- мы, а также некоторый набор таблиц лексем. Уже отмечалось, что в лексической свертке каждая лексема приводится к единому формату и представляется посредст- вом дескриптора, содержащего два вида информации: тип лексемы как синтаксиче- ской единицы, а также местоположение данной лексемы в таблице, соответствующей данному типу лексем. Для каждого языка программирования число различных типов лексем невелико, но в разных трансляторах может различаться. Какие цепочки сим- волов считать лексемами и какие их типы выделять, зависит не только от языка про- граммирования, но и от выбранных алгоритмов трансляции Обычными типами лексем являются: идентификаторы, используемые как имена (не- зависимо от того, используются ли они для именования переменных, функций, меток и т. д., все идентификаторы обычно попадают в один класс лексем); служебные слова (которые либо являются подмножеством идентификаторов в таких языках, как ПЛ/1 или Фортран, где цепочка DO 20 I — переменная в операторе DO 20 I = 1.25, а цепочка DO — служебное слово в операторе DO 20 I = 1,25; либо последовательностью маркированных букв, как _начало_ в языке Минал); числовые константы; разделители (+, —, **, := и т. д.); примечания. Обычно лексический анализ также включает определенные операции редактирова- ния. Это вызвано тем, что для одного и того же языка, как правило, существует не- сколько различных внешних представлений, связанных с различными внешними но- сителями. При этом часто возникает необходимость в перекодировании символов. По разным причинам текст входной программы может содержать избыточные символы, такие как пробелы или символы перехода на новую строку, которые должны быть удалены из программы. Существуют периферийные устройства, которые допускают возврат каретки при помощи клавиши "шаг назад" или позволяют "стирать" один из ранее набранных символов с помощью символа вычеркивания. Эти средства позво- ляют перепечатывать символы и требуют включения в операции редактирования опе- раций по перестройке строки, для реализации которых необходимо предусмотреть буфер. В процессе выделения лексем сканеру доступна некоторая контекстная информация. Эта информация может быть использована для преобразования лексической свертки к виду, более удобному для дальнейшей обработки. Например, язык Минал, являю- щийся подмножеством языка Алгол-60, может быть описан так называемой грамма- тикой простого предшествования (см. разд. 7.3.3), если использовать два различных символа вместо символа в качестве ограничителя метки и в описании массива. Такая расклейка символа для лексического анализа является довольно тривиаль- ной задачей, поскольку использование символа в описании массива всегда встре- чается между символом массив и первым следующим за ним символом С другой стороны, такое преобразование позволяет на этапе синтаксического анализа восполь-
548 Часть II. Применение графов и граф-моделей зоваться алгоритмом простого предшествования вместо (необходимого ранее) неко- торого более общего и менее эффективного алгоритма синтаксического анализа. При лексическом анализе, помимо чисто лексического контроля, связанного с выяв- лением и, возможно, исправлением ошибок в записи лексем, иногда выполняется по- верхностный синтаксический контроль Например, проверяется парность некоторых основных символов, таких как начало и конец, если и то, для и цикл, (и), [и] в язы- ке Алгол-60. Другой вид такого контроля — это проверка сочетаемости (допустимо- сти в какой-нибудь синтаксически правильной программе) стоящих рядом символов. Например, для языка Алгол-60 пара символов иначе начало сочетаема, но те же сим- волы, стоящие в обратном порядке (начало иначе), не сочетаемы. 7.3.3. Реализация лексического анализатора Сканер можно запрограммировать как отдельный просмотр, на котором осуществля- ется лексический анализ всей исходной программы. При таком подходе (см. разд. 7 7) сканер передает синтаксическому анализу целиком внутреннее представление исход- ной программы, состоящее из таблиц и лексической свертки программы. Обычный вариант, однако, состоит в том, что сканер реализуется в виде набора подпрограмм, к которым обращается синтаксический анализатор всякий раз, когда ему необходим новый символ. При этом набор подпрограмм может быть организован таким образом, что для дан- ной входной цепочки и положения указателя, фиксирующего текущий символ, сканер определяет лексему, левый символ которой является текущим символом, и сдвигает указатель непосредственно вправо за эту лексему. В этом случае говорят, что сканер работает прямо. Например, при обработке Фортран-программы для цепочки сим- волов DO 20 I = 1,25 с указателем, расположенным на левом конце, прямой сканер, просмотрев текст вплоть до запятой, придет к заключению, что очередной лексемой является служеб- ное слово DO, и продвинет указатель на два символа вправо. Другой способ организации набора подпрограмм сканера используется в том случае, когда при обращении к сканеру за лексемой ему дополнительно указывается тип этой лексемы. В этом случае сканер определяет, образуют ли символы входной цепочки, расположенные непосредственно справа от указателя, лексему указанного типа, и если да, то передвигает указатель за эту лексему. О таком способе организации гово- рят, что сканер работает не прямо. Для рассмотренной ранее цепочки DO 20 I = 1,25 с тем же положением указателя непрямой сканер ответит "Да", если его спросят о служебном слове DO, причем указатель передвигается на два символа вправо; либо ответит "Да" и передвинет указатель на 7 символов вправо, если его спросят о лексе- ме, являющейся идентификатором. На практике существуют комбинации прямой и непрямой организации сканера.
Глава 7. Синтаксические деревья 549 Следует также заметить, что успех в выборе отображения информационных мно- жеств, образованных лексемами одного и того же типа, во многом определяет эффек- тивность работы сканера. Сканер работает исключительно с локальной информацией о входной строке, если и превышающей, то несущественно ту последовательность входных символов, которую нужно ему свернуть в лексему. Это значительно усложняет задачу сканера по обра- ботке так называемых лексических ошибок —тех ситуаций, когда сканер окажется не в состоянии выделить лексему в доступном ему префиксе еще не обработанной части входной цепочки. Обычный подход к повышению надежности обработки сканером лексических ошибок состоит в предоставлении ему со стороны синтаксического ана- лизатора (и других частей транслятора) некоторой дополнительной информации (на- пример, списка тех лексем или типов лексем, появление которых законно ожидать в текущем контексте). Имеется ряд ситуаций, в которых применение в сканере той или иной стратегии ми- нимальной коррекции (например, в терминах таких операций, как вставка, удаление или изменение символа) избавляет нас от новых (наведенных) ошибок. Например, в языке Паскаль любая разумная метрика исправлений позволяет в префиксе 1Аг вы- делить три лексемы "1", "А" и Тем не менее в большинстве случаев обработку лексических ошибок неразумно рассматривать в качестве внутренней функции скане- ра. и она должна осуществляться под контролем других частей транслятора (главным образом, синтаксического анализатора). 7.4. Синтаксический анализ Выходом лексического анализатора (сканера) является лексическая свертка трансли- руемой программы. Процесс дальнейшей трансляции состоит в разборе (или синтак- сическом анализе) структуры вхождений понятий в лексическую свертку программы и проверке, удовлетворяет ли эта структура синтаксису языка. То, что в качестве ре- зультата (и задачи) синтаксического анализа рассматривается построение дерева раз- бора, ни в коей мере не означает, что в некоторый момент трансляции это дерево бу- дет физически построено. Тем не менее, рассматривая выполнение любого алгоритма синтаксического анализа, можно всегда проследить в нем процесс построения дерева разбора. 7.4.1. Стратегии разбора В процессе синтаксического анализа лексическая свертка программы обычно про- сматривается слева направо (и мы ограничимся рассмотрением только таких алго- ритмов). Если программа допустима, то этот процесс завершается построением одно- го из ее деревьев разбора. Узнавая на каждом следующем шаге все большее число символов из лексической свертки транслируемой программы (и, таким образом, узна- вая все большее число висячих вершин ее дерева разбора), анализатор пытается по- строить дерево разбора (возможно, не одно, а несколько — все или часть из тех, ко- торые согласуются с уже имеющейся информацией о программе), как бы заполняя
550 Часть II. Применение графов и граф-моделей его внутренними вершинами в некотором порядке В принципе, возможен выбор произвольного порядка заполнения дерева в процессе анализа. Однако этот порядок может в большей степени влиять на эффективность разбора в смысле как трудоемко- сти, так и работы с ошибками (по отношению к той или иной конкретной граммати- ке). Этот порядок также тесно связан со всем процессом трансляции. В большинстве существующих методов разбора порядок заполнения дерева сводится к одному из двух основных вариантов (стратегий): сверху вниз и снизу вверх. При заполнении сверху вниз (стратегия так называемого нисходящего анализа) все пред- шественники каждой заполняемой в дереве внутренней вершины к этому моменту уже заполнены. Заполнение снизу вверх (стратегия так называемого восходящего анализа) характеризуется тем, что все преемники каждой заполняемой в дереве вер- шины уже принадлежат построенной части дерева. Таким образом, при заполнении дерева при нисходящем анализе движение осуществляется от его корня к висячим вершинам, а при восходящем — от висячих вершин к корню. В последнее время ста- ли появляться алгоритмы разбора, у которых стратегия заполнения вершинами дерева разбора характеризуется тем, что на каждом шаге работы такого алгоритма все пред- шественники каждой заполненной вершины дерева (в том числе и каждой висячей вершины) уже заполнены. Таким образом, эти алгоритмы в чистом виде не реализуют ни восходящего, ни нисходящего разбора. Описанную стратегию мы называем стра- тегией горизонтального анализа. Вместе с тем, как правило, каждый шаг горизон- тального разбора распадается на более мелкие шаги так называемого замыкания, в процессе которого происходит заполнение дерева разбора от сыновей к отцам (т. е. снизу вверх). Поэтому многие авторы относят алгоритмы данного класса также к вос- ходящему анализу и рассматривают только две стратегии: восходящего и нисходяще- го анализа В каждой из перечисленных стратегий можно реализовать алгоритм анализа для про- извольного КС-языка. Однако такой разбор не будет столь эффективным, чтобы быть применимым на практике, и будет содержать большое количество проб и ошибок. Впрочем, можно определить ограниченные классы грамматик, которые поддаются более эффективному анализу в той или иной из указанных стратегий. Естественно, эти ограниченные классы грамматик являются менее гибкими как с точки зрения по- лучаемых языков, так и по способам порождения предложений. Следует заметить, что при разработке языков программирования обычно стремятся к простоте записи программ на этом языке (а также к простоте реализации языка), по- этому синтаксис большинства существующих языков программирования допускает задание грамматиками, принадлежащими одному из указанных ограниченных классов. 7.4.2. Автоматы с магазинной памятью Автомат с магазинной памятью (МП-автомат) — это распознаватель, состоящий из трех частей (рис. 7.7): входной ленты, управляющего устройства с конечной памятью и вспомогательной памяти, используемой в режиме магазина (стека), т. е в каждый момент доступен только верхний элемент магазина. МП-автомат представляет собой естественную модель синтаксических анализаторов КС-языков. Язык контекстно-
Глава 7. Синтаксические деревья 551 свободен тогда и только тогда, когда он допускается недетерминированным МП- автоматом. Особенно важным с точки зрения анализируемости языков является под- класс КС-языков, состоящий из детерминированных КС-языков, т. е. языков, распо- знаваемых детерминированными МП-автоматами. Рис. 7.7. Автомат с магазинной памятью (МП-автомат) Входная лента—это потенциально неограниченная вправо линейная последователь- ность клеток (или ячеек), каждая из которых может содержать любой символ из неко- торого заданного входного алфавита. Входная головка в каждый момент обозревает входную ячейку, содержимое которой доступно для чтения в данный момент. За один такт работы МП-автомата входная головка может сдвинуться на одну ячейку вправо или остаться неподвижной. Управляющее устройство МП-распознавателя состоит из конечного множества внутренних состояний, среди которых выделены начальное состояние и множество заключительных состояний; а также из управляющего отображения, описывающего, в какое внутреннее состояние перейти, какую информацию поместить в магазин и как изменить положение входной головки в соответствии с обозреваемым входным сим- волом, текущим внутренним состоянием и информацией, извлеченной из магазина. Конфигурация МП-распознавателя — это состояние управляющего устройства, не- прочитанная часть входной цепочки, самый левый символ, который обозревается входной головкой, а также содержимое магазина. Среди множества всех конфигура- ций выделяются множества начальных и заключительных конфигураций. В началь- ной конфигурации входная головка обозревает левый символ входной цепочки, управляющее устройство находится в начальном состоянии, а магазин содержит спе- циальный начальный символ Н, принадлежащий алфавиту магазинных символов МП- автомата. В заключительной конфигурации входная головка обозревает ячейку, рас- положенную справа от входной цепочки, управляющее устройство находится в одном из заключительных состояний, а магазин — пуст. МП-распознаватель работает, проделывая некоторую последовательность шагов (так- тов) и переходя от одной конфигурации к другой в соответствии с управляющим ото-
552 Часть II. Применение графов и граф-моделей бражением. При этом распознаватель называется детерминированным, если для каж- дой конфигурации существует не более одного допустимого шага, и недетерминиро- ванным, если таких шагов может быть несколько. Говоря!, что МП-распознаватель допускает входную цепочку а, если, начиная с на- чальной конфигурации, в которой а записана на входной ленте, он может проделать в соответствии с управляющим отображением последовательность шагов, заканчи- вающуюся заключительной конфигурацией. Язык, определяемый (или допускаемый) МП-распознавателем, — это множество всех цепочек, которые он допускает. Управляющее отображение МП-распознавателя задается в виде последовательности команд (Л, а, Ь) (8, С, а), где А— текущее внутреннее состояние; а— обозреваемый головкой символ; b — символ, находящийся в верхушке магазина и извлекаемый на этом такте; 8=1, если входная головка сдвигается вправо, и 8 = 0, если она сохраняет свое положение; С — следующее состояние; а — цепочка во внутреннем алфавите, записываемая в магазин на этом такте (ее правый символ записывается первым) Например, распознаватель, допускающий язык ЦГ0), где Го— грамматика арифме- тических выражений (см. разд. 7.2.3), может иметь следующий вид. Набор команд определяется множеством схем команд, в которых b обозначает любой символ из множества {а, +, *, (,)}: (Л, b, Н) -» {(О, С, Е/7)}, (С, b, Е) -> {(О, С, Е+Т), (О, С, Г)}, (С, b, Г) -> {(О, С, Г* F), (О, С, £)}, (С, Ь, F) -> {(О, С, (Е)), (О, С, а)}, (С, Ь, Ь) -> {(1, С, е)}, (С, В,Н)-+ {(О, D, е)} . Например, первая схема команд определяет такие пять команд МП-распознавателя: (А, а,Н)-> {(О, С, ЕН)}, (А, +, Н) -> {(О, С, ЕН)}, (А,*,Н)-> {(О, С, ЕН)}, (А, (,Н)-> {(О, С, ЕН)}, (А,), Н) -> {(О, С, ЕН)}. В МП-распознавателе состояние А является начальным, а {£)} это множество за- ключительных состояний. Обозначим конфигурацию распознавателя тройкой (С, ot, Р), где С — состояние, а — неиспользованная часть входной цепочки, Р — содержимое магазина (самый левый символ цепочки р является верхним символом магазина). Получаем, что для входной
Глава 7. Синтаксические деревья 553 цепочки a + a * а возможна среди других следующая последовательность конфигура- ций: (A, a + a * а, Н), (С, a + a * а, EH), (C, a + a * a, E + TH), (C, a + a * a, T + TH), (C, a + a * a, F + TH), (C, a + a * a, a + TH), (C, + a * a, + TH), (C, a * a, TH), (C, a * a, T * FH), (C, a * a, F * FH), (C, a * a, a * FH), (C, * a * FH), (C, a, FH), (C, a, aH), (С, e, H), (D, e, e). По существу, этот распознаватель недетерминированно порождает все предложения языка и сравнивает их с входной цепочкой, попадая в заключитель- ную конфигурацию (т. е. конфигурацию вида (D, е, е), где D — заключительное со- стояние) тогда и только тогда, когда одно из порождаемых предложений совпадает с входной цепочкой Можно рассматривать различные обобщения понятия МП-распознавателя. Одно из таких обобщений связано с тем, что на каждом такте МП-распознаватель может из- влекать из магазина ограниченной длины цепочку верхних символов магазина (в ча- стности, пустую цепочку). Такой обобщенный распознаватель для языка £(Г()) может иметь следующую последовательность схем команд: (A, b, Н)->{(], С, М)}, (С,Ь, е)->{(l, С, Ь)}, (С, d, Т) {(О, С, Е)}, (C,d,E+T)-+ {(О, С, £)}, (С, d, Т* F)^> {(О, С, Т)}, (С, d, F) -> {(О, С, Т)}, (С, d, (£)) {(О, С, F)}, (С, d, a) {(О, С, F)}, (С, В, ЕН) {(О, D, е)} для всех Ь е {а, +, *, (,)} и d е {а, +, *, (,), В}. Здесь А — начальное состояние, а {D} — множество заключительных. Для входа а + а * а распознаватель может пройти следующую последовательность конфигураций: (А, а + а* а, Н), (С, + а * а, аН), (С, + а * a, FH), (С, + a* a, TH), (С, а * а, + TH), (С, * а, а + TH), (С, *а, F + TH), (C,a,*F+ TH), (С, е, a* F + TH), (С, е, F * F + TH), (С, е, Т * F + TH), (С, е, Т+ TH), (С, е,Е+ TH), (С, е, ЕН), (D, е, е). Поскольку при таком обобщении из магазина извлекаются цепочки ограниченной длины в конечном наборе символов, т. е. такие, которые можно рассматривать как коды символов некоторого другого конечного набора символов, то это обобщение не увеличивает класса допускаемых языков. 7.4.3. Нисходящий МП-распознаватель Алгоритмы нисходящего синтаксического анализа связаны с моделированием так называемого нисходящего Л//7-распознавателя, который осуществляет распознавание путем недетерминированного порождения левого вывода предложения языка и срав-
554 Часть II. Применение графов и граф-моделей нения его с распознаваемой цепочкой. Пример такого М/7-распознавателя для грам- матики Го приведен в разд. 7.4.2. Рассмотрим дерево левых выводов некоторой грамматики Г = (К, W, Е, Р). Это дерево рекурсивно определяется следующим образом: корню дерева сопоставлена цепочка, состоящая из единственного символа Е; если цепочка а сопоставлена некоторой вер- шине р дерева, то для каждой цепочки р, получаемой левой подстановкой из а, заво- дится вершина дерева и объявляется преемником вершины р. Введем также следую- щие термины. Терминальным префиксом некоторой цепочки а будем называть наи- большей длины префикс цепочки а, состоящий из терминалов. Будем говорить, что цепочка а согласуется с цепочкой р, если терминальный префикс цепочки а является префиксом цепочки Р, либо Р является префиксом цепочки а. В терминах дерева левых выводов работа нисходящего М/7-распознавателя может быть описана следующим образом. Если распознается предложение, то, начиная с корня этого дерева, распознаватель на каждом шаге недетерминированно переходит к одному из преемников изучаемой вершины до тех пор, пока цепочка этой вершины не совпадает с распознаваемым предложением. Если же распознаваемая цепочка не является предложением, то распознаватель убеждается в том, что в дереве левых вы- водов нет вершины, цепочка которой совпадала бы с рассматриваемой цепочкой. Обычный подход к моделированию нисходящего распознавателя связан с реализаци- ей специального обхода тех вершин дерева левых выводов, цепочки которых согла- суются с входной цепочкой. Такие вершины называются достижимыми относительно данной входной цепочки. При этом используется очевидное свойство, что преемник недостижимой вершины является также недостижимой вершиной. При описании алгоритма будем предполагать, что все преемники каждой вершины дерева левых выводов каким-то образом упорядочены. проц НИСХОДЯЩИЙ АНАЛИЗ = 1. Объявляем корень дерева левых выводов рассматриваемой вершиной; 2. если цепочка рассматриваемой вершины совпадает с входной то на 11 3. иначе выбираем среди преемников рассматриваемой вершины первую достижимую вершину, которая ранее не рассматривалась. 4. если такая вершина найдется то 5. Объявляем ее рассматриваемой и переходим на 2 6. все; 7. ВОЗВРАТ: если рассматриваемая вершина имеет предшественника то 8. Объявляем его рассматриваемой вершиной и переходим на 2 9. иначе стоп % Входная цепочка не является предложением % все; 10. % Входная цепочка является предложением %; все Сделаем несколько замечаний к алгоритму. Дерево вывода. При движении по дереву левых выводов мы всегда можем иметь де- рево вывода цепочки рассматриваемой вершины. При этом переход от рассматривав-
Глава 7. Синтаксические деревья 555 мой вершины к рассмотрению ее достижимого преемника соответствует добавлению всех преемников к первой висячей вершине дерева вывода, помеченной нетермина- лом, а переход к предшественнику рассматриваемой вершины — удалению висячих вершин дерева вывода, образующих основу. Далее мы можем занумеровать все пра- вила и упорядочить всех преемников каждой вершины дерева левых выводов в соот- ветствии с номерами применяемых правил. Это означает, что если каждую вершину дерева вывода метить номером правила, с помощью которого мы последний раз пы- тались добавить преемников к этой вершине, то действия каждого шага работы алго- ритма полностью определяются в терминах текущего состояния построенного дерева вывода и его пометок. Проблема остановки. Время работы нисходящего анализа по распознаванию некото- рой цепочки а связано с числом вершин дерева левых выводов, достижимых относи- тельно а. Нетрудно видеть, что таких вершин может быть бесконечно много даже для однозначной грамматики, если она является рекурсивной слева, поскольку может существовать левый вывод Е =>* г]Ар => г)Л8, где г| согласуется с б. Поэтому, чтобы гарантировать конечность любого пути по дереву левых выводов от его корня до пер- вой вершины, у которой цепочка либо не согласуется с исходной цепочкой, либо сов- падает с ней, мы должны потребовать, чтобы грамматика не являлась рекурсивной слева. Локализация ошибок. Описанный метод обладает слабыми возможностями в смысле локализации ошибок— если входная цепочка не является предложением, то он про- сто объявит о том, что программа недопустима (нельзя отличить возврат, вызванный ошибкой, от возврата, возникшего из-за неправильной попытки). Чтобы получить более подробную информацию, можно добавить в грамматику специальные правила, порождающие распространенные ошибки, и использовать их появление в выводе как сигнал появления ошибки во входной цепочке. Однако этот прием нельзя признать достаточно практичным. Приемы эффективизации. Известен ряд приемов, позволяющих слегка ускорить опи- санный метод. Например, если грамматика не содержит е-правил, мы можем не рас- сматривать те вершины дерева левых выводов, длины цепочек которых превышают длину входной цепочки, и таким образом исключить зацикливание алгоритма анализа даже для рекурсивных слева грамматик. Можно уменьшить число возвратов при рас- познавании предложения языка, упорядочивая правила грамматики таким образом, чтобы проверять наиболее вероятные альтернативы первыми. Перед каждым до- строением дерева вывода можно также осуществлять просмотр на несколько симво- лов вперед по входной цепочке и определять, надо ли пытаться использовать рас- сматриваемое правило для построения в текущей ситуации или нет, если из него (из правой части этого правила) не выводится цепочка, префиксом которой являются эти символы. Однако все эти и другие известные приемы в общем случае не делают алго- ритм существенно более эффективным, и число шагов, необходимых для разбора с помощью этого алгоритма, может быть огромным Мы увидим, что для ограничен- ных классов грамматик с помощью просмотра вперед можно полностью устранить необходимость возвратов.
556 Часть II. Применение графов и граф-моделей 7.4.4. LL-грамматики и LL-распознаватель Рассмотрим более подробно модификацию алгоритма нисходящего разбора, связан- ную с просмотром вперед на к символов. В этом случае каждая вершина дерева левых выводов р снабжается последовательностью так называемых контекстных множеств М\{р), М2{р), ..., Mfp), где I — число преемников у р. Эти контекстные множества для некоторой вершины р определяются следующим образом. Пусть р — терминальный префикс цепочки, сопоставленной вершине р, тогда некоторая у принадлежит М,(р) в том и только том случае, если из Z-го преемника вершины р достижима вершина цепочка которой содержит только терминалы и представима в виде Руту, где либо т] — пустая цепочка и |у | < к, либо |у| — к и г] е. Модификация общего нисходящего алгоритма (получившая название LL-анализа- тора) связана с изменением понятия достижимости некоторой вершины дерева ле- вых выводов относительно цепочки а. В ££-анализаторе понятие достижимости оп- ределяется следующим образом. Корень дерева достижим относительно а, если его контекстные множества содержат цепочку, являющуюся префиксом цепочки а; вер- шина р с предшественником q достижима относительно а, если цепочка а предста- вима в виде Рут], где Р — терминальный префикс цепочки, сопоставленной вершине q, а у принадлежит множеству M,{q), если р — i-й преемник у q. Ясно, что таким образом модифицированный алгоритм будет безвозвратным при распознавании предложения (или, что то же самое, детерминированным) тогда и только тогда, когда не будут пересекаться два любых контекстных множества каждой вершины дерева левых выводов1. Грамматики, удовлетворяющие этому свойству, получили название ££(£)-грамматик. Грамматика называется ££-грамматикой, если она ££(£)-грамматика для некоторого к. Заметим, что, так изменив понятие достижимости и работая с ££-грамматикой с по- мощью процедуры НИСХОДЯЩЕГО АНАЛИЗА {см. разд 7.4.3), мы тем не менее можем прийти к выполнению возврата (оператор 8). Однако это возможно в том и только в том случае, когда входная цепочка не является предложением; причем пер- вый возврат осуществляется сразу же, как только рассматриваемая часть входной цепочки перестает быть префиксом предложения в данной ££-грамматике. Это делает ££-анализатор (в операторе возврата которого сгруппированы действия, связанные с обработкой ошибок) удобным для работы с недопустимыми программами. Рассмотрим частный случай ££(£)-грамматик, в которых к = 1 и нет е-правил. Ясно, что при таких ограничениях для любых двух правил с одинаковой левой частью спра- ведливо следующее. Пусть аир — правые части этих правил, тогда любая цепочка, выводимая из а, не начинается с терминала, с которого может начинаться цепочка, выводимая из р. Это дает возможность организовать анализатор в виде набора про- 1 Заметим, что этим ликвидируются не только явные возвраты нисходящего анализа при распознавании предложения (т. е. те, которые вынесены в ВОЗВРАТ), но и неявные, которые связаны с поиском дости- жимого преемника рассматриваемой вершины при выполнении ШАГа.
Глава 7. Синтаксические деревья 557 цедур: по одной процедуре для каждого нетерминала и по одной процедуре для каж- дого вхождения терминала в правые части правил грамматики. Каждая процедура, связанная с некоторым вхождением терминала, осуществляет сравнение указанного терминала с первым символом входной строки и в случае их несовпадения сигнализирует об ошибке (и может осуществить некоторые другие дей- ствия, связанные с обработкой данной ошибки), а в случае совпадения удаляет пер- вый символ из входной строки. Процедура, связанная с некоторым нетерминалом А, имеет вид оператора выбора, число альтернатив которого — это число правил, у ко- торых А — левая часть плюс единица. Выбор состоит в рассмотрении первого симво- ла входной строки и переходе к альтернативе либо обрабатывающей соответствую- щее правило, либо содержащей обработку ошибки. Обработка некоторого правила А -> <7| оэ ••• представляет собой последовательность вызовов процедур, связанных с <7Ь а2, ..., as соответственно. Поскольку возможно, что а, = А для некоторого I, эта процедура в общем случае является рекурсивной. Работа анализатора, построенного таким обра- зом (получившая название рекурсивного спуска), начинается с вызова процедуры, ассоциированной с символом программы. Эта процедура в процессе своего выполне- ния осуществляет рекурсивные вызовы других процедур; а пустота входной строки в момент ее нормального завершения говорит о том, что разбираемая цепочка являет- ся предложением. 7.4.5. Восходящий Л4/7-распознаватель Алгоритмы синтаксического анализа, реализующие восходящую стратегию, связаны с моделированием так называемого восходящего М/У-распознавателя, в котором пра- вила подстановки недетерминированно и "в обратном направлении" применяются к входной цепочке с тем, чтобы породить такую последовательность цепочек ос1;..., сс„„ что ее обращение (т. е. последовательность ос,„ => а,„_| => ..., => а,) представляет со- бой правый выход входной цепочки. Пусть некоторая цепочка а имеет вид ург] и пусть в грамматике существует правило А -> р. Тогда будем говорить, что редукция цепочки а относительно правила А —> р определена, если цепочка у не содержит нетерминалов; эта редукция состоит в преоб- разовании цепочки а в цепочку уЛг]. При этом будем называть у — левым, а г] — пра- вым контекстами данной редукции. Понятно, что если существует правый вывод Е =>’ уА г] => уРп, то Р является основой дерева вывода, представляющего данный вывод. Рассмотрим дерево редукций некоторой входной цепочки а, определяемое следую- щим образом: корню дерева соответствует цепочка а; если некоторая цепочка Р со- поставлена некоторой вершине р, то для каждой возможной редукции цепочки р за- водится новая вершина дерева— преемник вершины р, которому ставится в соответ- ствие цепочка, получаемая в результате этой редукции. В терминах дерева редукций
558 Часть II. Применение графов и граф-моделей работа восходящего МТУ-распознавателя описывается следующим образом. Начиная с корня дерева и недетерминированно переходя на каждом шаге к рассмотрению од- ного из преемников рассматриваемой вершины, распознаватель либо достигает вер- шины, которой соответствует цепочка Е, если а — предложение, либо убеждается, что в дереве нет такой вершины, если а не является предложением. Обычный подход к моделированию работы восходящего М/7-распознавателя с неко- торой цепочкой а связан с реализацией поиска в глубину по дереву редукций цепочки а. Предполагается упорядоченность правил грамматики, на основе которой опреде- ляется порядок преемников каждой вершины дерева, редукций следующим образом. Вершина р предшествует вершине q тогда и только тогда, когда для редукций Р(р) и P(q), соответствующих вершинам р и q, выполнено одно из следующих свойств: пра- вый контекст редукции Р(р) превышает по длине правый контекст редукции Р(дУ, длины правых контекстов редукций Р(р) и P(q) совпадают, но правило, относительно которого осуществляется редукция Р(р), предшествует соответствующему правилу редукции P(q). проц ВОСХОДЯЩИЙ АНАЛИЗ = 1. Объявляем корень дерева редукций рассматриваемой вершиной; 2. если цепочка рассматриваемой вершины совпадает с входной то на 11 3. иначе выбираем среди преемников рассматриваемой вершины еще не рассмотренную вершину 4. если такая вершина найдется то 5. Объявляем ее рассматриваемой и переходим на 2 6. все; 7. ВОЗВРАТ: если рассматриваемая вершина имеет предшественника то 8. Объявляем его рассматриваемой вершиной и переходим на 2 9. иначе стоп % Входная цепочка не является предложением % все; 10. % Входная цепочка является предложением %; все Сделаем несколько замечаний. Дерево вывода. Можно переформулировать работу алгоритма в терминах работы с деревом вывода. При этом переход от рассматриваемой вершины к рассмотрению ее преемника связан с добавлением вершины в дерево, а выполнение возврата (опера- тор 8) — удалением вершины из дерева. Проблема остановки. Алгоритм не зацикливается, если грамматика не содержит е-правил и не существует, А =>+ А, что связано с наличием цепных правил в грамма- тике. Проблема возвратов. Из-за громадного количества возможных возвратов алгоритм восходящего анализа в чистом виде является очень неэффективным; он также плохо приспособлен для обработки недопустимых программ. Для преодоления возвратов восходящий анализ должен быть организован таким образом, чтобы по префиксу лю-
Глава 7. Синтаксические деревья 559 бой правовыводимой цепочки, содержащему основу этой цепочки, он мог однозначно определять необходимую редукцию, т. е. основу цепочки и то правило грамматики, которое должно быть применимо. В общем случае это сделать невозможно и возвра- ты сохраняются, хотя можно указать ряд методов, которые несколько уменьшают их количество. Однако если рассматривать более ограниченные классы, чем КС-языки, то можно указать довольно простые критерии, позволяющие восходящему анализу избегать возвратов. 7.4.6. Грамматики предшествования Рассмотрим следующие три отношения между символами грамматики. Первое отношение, обозначаемое символом =, состоит из множества всех таких пар символов А и D (обозначаем А = D), которые расположены рядом (в указанном по- рядке) в основе некоторой правовыводимой цепочки1. Два символа А и D находятся в отношении, записываемом в виде А < D, тогда и толь- ко тогда, когда А и D расположены рядом в некоторой правовыводимой цепочке та- ким образом, что А — непосредственно предшествует основе, a D— первый символ основы. Отношение > определяется аналогично отношению < с тем отличием, что А > D, если А завершает основу некоторой правовыводимой цепочки, a D в этой цепочке следует непосредственно за основой2. На первый взгляд кажется, что нахождение этих отношений для некоторой грамматики требует рассмотрения всех ее правых вы- водов, однако довольно простые для проверки условия их выполнения можно сфор- мулировать в терминах грамматических правил (см. разд. 7.5.3). Понятно, что если между любыми двумя символами грамматики выполняется не бо- лее одного отношения и в грамматике нет е-правил, то в процессе восходящего ана- лиза предложения языка мы всегда будем правильно выделять основу; причем, если в грамматике также не будет двух правил с одинаковыми правыми частями, возвратов не потребуется. Грамматики, удовлетворяющие указанным двум условиям, получили название грамматик простого предшествования. Например, грамматика Го не является грамматикой простого предшествования, по- скольку в ней + = Т и +<. Т, а также ( = Е и ( < Е. Однако путем добавления нетер- миналов она может быть преобразована в грамматику £-»£>, D -> Т | D + Т, Т-+К, 1 Заметим, что отношение не обязательно симметрично, т. е. если А = D, то у нас нет причин утверждать, что А = D. 2 Если А > D, то D — терминал.
560 Часть II. Применение графов и граф-моделей K->F\K*F, F—>(.E)\a, которая является грамматикой простого предшествования. Алгоритм восходящего анализа для рассматриваемого класса грамматик очень прост. Работа его начинается с исполнения СДВИГа при пустом рабочем СТЕКе и ВХОДе, содержащем разбираемую цепочку. проц АНАЛИЗ ПРОСТОГО ПРЕДШЕСТВОВАНИЯ = 1. ВХОД = входная цепочка СТЕК := 0; 2. СДВИГ: Помещаем первый символ из ВХОДа в СТЕК; 3. СРАВНЕНИЕ: если ВХОД пустая цепочка то переходим на РЕДУКЦИЮ 4. иначе А = Э СТЕК; D ;= Э ВХОД; 5. если (А = D)v(A < D) то на 2 6 иначе если А > D то на 7 7. иначе стоп % Входная цепочка не является предложением % все; все 8. РЕДУКЦИЯ: Пусть Ai...Ak — содержимое СТЕКа, где Ai — его верхний символ; 9. если не существует такого I, что А, > Ам, то на 15 10. иначе выбираем минимальное /, обладающее этим свойством; 11. если не существует правила А -> AiA2 ... А, то 12. стоп % Входная цепочка не является предложением % 13. иначе заменяем в СТЕКе цепочку AiA2 ... А, 14. символом А и переходим на 3 все все все; 15. ЗАВЕРШЕНИЕ: если ВХОД пуст, а в СТЕКе содержится цепочка, непосредственно выводимая из символа Е 16. то % Входная цепочка является предложением % 17. иначе % Входная цепочка не является предложением % все все При практической реализации описанного алгоритма возникает вопрос хранения ука- занных отношений. Занумеровав символы грамматики, можно хранить указанные отношения в виде так называемой матрицы предшествования — квадратного массива, содержащего tn элементов, где т— число символов грамматики. Однако в реальных языках про- граммирования число символов грамматики довольно велико (например, для языка Алгол-60 при синтаксическом анализе различается не менее 70 грамматических эле-
Глава 7. Синтаксические деревья 561 ментов, а в описании языка их 226), поэтому матрица предшествования на практике может быть довольно большой. Следует заметить, что обычно отношения определе- ны не для всех пар символов грамматики. Это дает возможность за счет увеличения времени поиска информации экономить память, используя различные методы сжатия разреженных матриц. Другой подход к хранению отношений предшествования связан с использованием так называемых функций предшествования Ф| и Ф2. Эти функции приписывают число- вые значения символам грамматики таким образом, что для любых символов А и D из выполнения одного из соотношений А = D, А < D н А > D следует соответст- венно Ф|(Л) = Ф2(£>), Ф|(Л) < Ф2(Л) и Ф2(Л) > Ф2(£>). Понятно, что функции предшествования для своего хранения требуют существенно меньших объемов памяти, поскольку они могут быть заданы двумя векторами по т элементов каждый. Однако эти функции существуют не для всех грамматик простого предшествования. Другим очень важным недостатком функции предшествования является то, что они задают отношения предшествования между каждой парой сим- волов и, таким образом, затрудняют работу с недопустимыми программами. В грамматике простого предшествования для определения основы использовалось по одному символу из ее правого и левого контекстов. Можно увеличить число рассмат- риваемых символов и таким образом расширить класс языков, распознаваемых с по- мощью описанного алгоритма. Например, для определения начала основы можно рассматривать не один, а два символа, предшествующих основе, а для определения ее конца — два символа, следующих за основой (так называемые грамматики (2.1)(1.2)- предшествования), или еще больший контекст. Однако для транслятора хранение от- ношений, связывающих три и более символа, становится обременительным с точки зрения объема памяти. Поэтому в том случае, когда между двумя символами сущест- вует более одного отношения, на практике либо перестраивают грамматику, вводя в нее новые символы, ибо отношения по двум символам дополняют отношениями по трем символам для тех пар, для которых существуют конфликтные ситуации. 7.4.7. Горизонтальный разбор Как восходящий, так и нисходящий разбор в общем случае работает с возвратами. Можно избежать возвратов при нисходящем разборе, если осуществить параллельное движение по дереву левых выводов, когда на каждом шаге рассматривается не одна, а некоторое множество ее вершин. Однако такой способ, при котором все попытки разбора производятся параллельно, связан с вопросом конечного кодирования беско- нечного числа возможных деревьев. Этот вопрос решается в горизонтальном разборе. Алгоритмы горизонтального анализа связаны со специальным способом рассмотре- ния вершин дерева разбора исходного предложения (в процессе чтения его символов слева направо). Этот способ, который мы будем называть горизонтальным движени- ем, характеризуется тем, что некоторая вершина р рассматривается тогда и только тогда, когда р является либо висячей вершиной, соответствующей читаемому симво- лу входного предложения, либо предшественником рассматриваемой вершины.
562 Часть II. Применение графов и граф-моделей В качестве примера рассмотрим простую грамматику {Е —> ЕВ | а, В —> he | d} и дерево разбора для некоторого предложения abed, которое мы будем изображать специальным образом (рис. 7.8). Если под этим деревом поместить исходное предло- жение, а границы шагов движения отметить штриховыми линиями, перейдем к кар- тине (рис. 7.9), из которой видно, что непосредственно после выполнения первого шага, на котором был прочитан символ а, мы закончили рассмотрение двух вершин дерева и собираемся перейти к рассмотрению еще двух вершин. Е Е В Е в а b с D Рис. 7.8. Дерево разбора цепочки abed Поскольку при горизонтальном движении рассмотрение некоторой вершины предпо- лагает одновременное рассмотрение ее преемников, это движение определяет также движение по правой части каждого правила, участвующего в выводе исходного пред- ложения. Например, после первого шага (при движении по дереву разбора предложе- ния abed) полностью пройдены правая часть правила £ -э о и один символ в правой части правила Е —> ЕВ. Рис. 7.9. Шаги горизонтального движения С каждым /-м шагом горизонтального движения связывается множество состояний 51,, описывающих положения при движении по правилам грамматики непосредственно перед выполнением /-го шага. Каждое состояние из S,— это пара [А —> сс-р | /], со- стоящая из некоторого правила А —> сс-р, в которой точка разделяет правую часть правила на две части — ту часть, которая уже пройдена до /-го шага, и ту часть, кото- рую предстоит пройти на следующих шагах, а также из числа / — номера шага, на
Глава 7. Синтаксические деревья 563 котором начинается движение по данному правилу. Для нашего примера множества состояний имеют следующий вид: So= {[£—> ЕВ |0 ], [Е—> сс| 0]}, S’, - {[Е -> Е -В | 0], [Е -> я -| 0], [В -> be | 1]}, В2={[В->/>с| 1]}, S3={\B-+bc\ 1], {Е-> ЕВ-|0], [£-> Е В | 0], [В ->ч/| 3]}, В4 = {[В -> с7 |3], [Е -> ЕВ |0]} На первый взгляд кажется, что рассмотренные множества состояний не дают полного описания горизонтального движения, поскольку, например, в нашем примере So ни- как не отражает того факта, что на первом шаге начинается рассмотрение нескольких вершин, каждая из которых имеет пометку Е и преемников с пометками Е и В, а со- стояние S2 не содержит информации о том, что непосредственно перед вторым шагом рассматриваем три вершины дерева. Тем не менее для любого предложения совмест- ное рассмотрение его состояний позволяет восстановить дерево разбора данного предложения. Справедливы следующие свойства состояний, описывающих последовательность ша- гов горизонтального движения. А. Множество So содержит некоторое состояние [Е —> -сс| 0]. Б. Для любого /, если S, содержит некоторое состояние [В —> ссЛр | к\, где А — не- терминал, S, также содержит некоторое состояние [А —> у | /]. В. Для любого 1 > 0, если а — читаемый символ на i-м шаге и В, । содержит некото- рое состояние [А —> сс | А], то множество S, содержит состояние [А -> аа р | к]. Г. Для любого I > 0 из того, что некоторое состояние [А -> а-1 Л] содержится в S,u существует некоторое состояние [В —> у Ar] | L] в Sk, следует, что S, содержит состояние [В -> у А г] | /]. Д. Если п — длина исходного предложения, то S„ содержит некоторое состояние [Е->а|0]. Е. Для любого i некоторое состояние [А —> сс-р || Л] принадлежит S, только в том случае, если выполнено одно из следующих условий: П k = i, а = е и S< содержит некоторое состояние [С —> г]-А 5 | Z]; □ к < i; а = qfe, где b — читаемый на i-м шаге символ, a В/_, содержит состояние [А —> г] Лр | к]. (При выполнении этого условия мы будем называть состояние [А —> r]-fep | к\ "сестрой" состояния [А —> сер | к], если л * е); □ к = 0, i = 0, А = Е и а = е; П к < Г, а = г]В, где В— нетерминал, S, содержит некоторое состояние [В -> 5-| /], а S/ содержит состояние [А -> т] Вр | Л], (При выполнении этого условия мы будем
564 Часть II. Применение графов и граф-моделей говорить, что состояние [В —> 6-| /] является "дочерью" состояния [А —> а 0 | А], а также называть состояние [А —> грВ0 | к] "сестрой" состояния [А -> а 0 | А], если г) * е). Пусть So, —, S„— последовательность состояний горизонтального движения по дере- ву разбора исходного предложения. Добавим к этим состояниям фиктивное состояние [Е —> Е -| 0], дочерью которого объявим состояние [Е -> сс| 01, принадлежащее мно- жеству S„; и рассмотрим двоичное дерево состояний с отношениями дочь и сестра, корнем которого является фиктивное состояние Это двоичное дерево состояний для нашего примера будет иметь вид, приведенный на рис. 7 10. Здесь штриховая стрелка связывает состояние с его дочерью, а сплошная — с его сестрой. [Е >Е.10] [Е >Е.ВО] ----------------------------- [Е >ЕВ.О] [Е >Е.В|О] [Е->ЕВ_|О] [B->d.|3] [Е->а.|0] В->Ь.с|1]------[В->Ьс.|1] Рис. 7.10. Двоичное дерево состояний По существу, указанное двоичное дерево — это другая форма дерева разбора, помет- кой вершины которого является символ, расположенный в состоянии перед точкой; отношение "дочь" указывает на последнего (младшего) сына данной вершины, а от- ношение "сестра" связывает последующего сына с предыдущим, т. е. вершину с ее старшим братом. 7.4.8. Алгоритм Эрли Алгоритм горизонтального разбора в общем случае считывает символы входной це- почки слева направо и реализует одновременное горизонтальное движение по всем тем деревьям разбора, которые согласуются с уже рассмотренным префиксом вход- ной цепочки. Содержательно множество состояний после п шагов алгоритма, на ко- торых была прочитана цепочка 1], является объединением всех множеств состояний, которые можно получить, осуществив и шагов горизонтального движения по каждо- му из деревьев разбора предложений с префиксом г|. Понятно, что так определенное множество всегда будет конечным, поскольку существует только конечное число раз- личных пар [А -> сх-0 | А], в которых 0 < к < и.
Глава 7. Синтаксические деревья 565 проц АЛГОРИТМ ЭРЛИ = 1. В пустое множество So включаем для каждого правила е -> а состояние [Е -> а | 0]; устанавливаем номер шага / равным нулю; 2. ПОСТРОЕНИЕ ВНИЗ: Определяем минимальное множество состояний, содержащее S, и удовлетворяющее свойству, описанному в 7.4.7, Б. Это множество берем в качестве S/; 3. СДВИГ И ПОСТРОЕНИЕ ВВЕРХ: если прочитана вся входная цепочка то на 7 4. иначе считываем следующий символ из входной цепочки и увеличиваем значение /' на единицу. В качестве S, рассматриваем минимальное множество, удовлетворяющее свойству 7.4.7, В; 5. если некоторое состояние вида [А -» а | А] содержится* 1 в S, to увеличиваем S, таким образом, чтобы выполнялось свойство 7.4.7, Г, а каждое добавляемое состояние удовлетворяло свойству 4 из 7.4.7, Е; все; 6. на 2 все; 7. ЗАВЕРШЕНИЕ: если S, содержит состояние вида [Е -> a | 0] то входная цепочка является предложением 8. иначе входная цепочка не является предложением все все Таким образом, внутри каждого шага работы алгоритма Эрли (горизонтального раз- бора) в общем случае осуществляются попытки достроения дерева разбора как сверху вниз, так и снизу вверх, при этом отсекаются те вершины (те попытки), которые мо- гут быть построены при движении только снизу вверх или только сверху вниз. Время работы алгоритма Эрли пропорционально т3, где т — длина входной цепоч- ки, причем для однозначных грамматик временная граница пропорциональна т2, а для некоторых достаточно больших подмножеств однозначных грамматик даже ли- нейна. Следует заметить, что для нисходящего (или восходящего) анализа временная граница пропорциональна ст, где с— некоторая константа. Однако эти их верхние оценки трудоемкости не доказывают, что один метод анализа практически быстрее другого. 7.4.9. L/7-грамматики Алгоритм горизонтального разбора осуществляет одновременное горизонтальное движение по всем деревьям разбора, отсекая на каждом шаге те из них, которые не согласуются с префиксом входной цепочки, рассмотренным к этому шагу. 1 Наличие в S, некоторого состояния вида [Л -» a-1 к ] говорит о том, что существует правый вывод Е => Pai] => 8г], в котором 8— префикс входной цепочки, состоящий из i символов, а a — основа це- почки par].
566 Часть II. Применение графов и граф-моделей Этот алгоритм можно модифицировать, включив в него просмотр вперед на к симво- лов по входной цепочке, чтобы расширить возможности алгоритма заранее отсекать попытки (деревья), обреченные на неудачу. Каждое правило грамматики А —> а мож- но снабдить множеством A-символьных префиксов правых контекстов редукций от- носительно данного правила. Теперь предположим, что на некотором шаге алгоритма (при выполнении СДВИГ И ПОСТРОЕНИЕ ВВЕРХ) к множеству S, нужно добавить некоторое состояние [А -> сс-| А]. Однако нам известен возможный контекст правила А —> а и мы можем проверить, образуют ли к первых непрочитанных символов (из входной цепочки) цепочку из этого контекста. Если нет, то состояние [А —» а | /] можно не включать в S,. Понятно, что с ростом числа к способность к раннему отсечению у так модифициро- ванного алгоритма увеличивается. Однако одновременно с ростом к довольно быстро увеличивается объем памяти, необходимый для хранения контекстов правил, число символов в котором оценивается величиной к -Nk, где А— число терминалов в грам- матике. Эти дополнительные затраты с ростом к довольно быстро компенсируют те преимущества, которые получаются за счет раннего отсечения бесполезных попыток. Можно рассмотреть класс грамматик (так называемые РА(А)-грамматики), для кото- рых описанная модификация горизонтального анализа осуществляет полное отсече- ние деревьев, обреченных на неудачу. Этот класс грамматик довольно широк, по- скольку в момент определения редукции алгоритм неявно использует информацию, полученную из ее левого контекста, а также к символов правого контекста. Однако существует более широкий класс грамматик, поддающийся эффективному анализу. Этот класс, называемый LR, в точности порождает класс языков, распознаваемых детерминированными МП-распознавателями. Для него имеется возможность опреде- ления редукции, если известны полный контекст и правый контекст длины к предпо- лагаемой основы. Грамматика является ЬН(к)-грамматикой, если для любых двух правых выводов £'=>* рлб => Ру8 и Е' =>’ ссрсо =5- Руту в пополненной грамматике, полученной из ис- ходной путем добавления нового начального символа Е'и правила1 Е'—> Е, из того, что A-символьный префикс цепочки г) совпадает с A-символьным префиксом цепочки 5, следует, что А = В, а = р и 8 = т). Грамматика является ЬЕ-гра.мматикой, если она £Я(А)-грамматика для некоторого к. А. Для любой ЕЕ(к)-грамматики существует ЬЕ(1)-грамматика, порождающая тот же язык. 7.4.10. LR-анализатор По любой £/?(А)-грамматике можно автоматически построить так называемый £Я(А)-анализатор, осуществляющий разбор, чередуя сдвиги и редукции, с помощью двух магазинов (см. разд. 7.5.5). Один из магазинов, который мы будем обозначать 1 Если символ Е не встречается в правых частях правил исходной грамматики, то в определении £7?(А)-грамматнки вместо Е' можно взять Е (т. е. рассматривать правые выводы в исходной, а не в по- полненной грамматике)
Глава 7. Синтаксические деревья 567 МАП, служит для хранения цепочки (внутренних) состояний анализатора, а вто- рой — МАГ2 — для хранения редуцированного префикса входной цепочки. При сво- ей работе анализатор использует две функции— действия и переходов. Пусть X— множество состояний, а У— множество терминальных цепочек, длина каждой из которых не превышает k, а I = {1, 2, ..., и}, где и— число правил грамматики; тогда функция действия отображает множество пар х*У в множество пар 1 и {сдвиг, ошибка, допуск}, а функция перехода отображает множество пар A' ~x(V и W) в мно- жество А'и {ошибка}. В качестве небольшого примера рассмотрим следующую грамматику Г3: E-+S, S -> SaSb, S—> е. Она, как нетрудно заметить, является £/?(£)-грамматикой. Функции действия и пере- хода для грамматики Г3 можно задать таблицами, приведенными на рис. 7.11. Здесь С— сдвиг, О— ошибка, D— допуск, {£0, 7), Тг, Т3, Т5, Т6, 7’7}— множество состояний, То — начальное состояние. А b с Sab То 3 0 3 То Т1 0 0 Ti С 0 D Ti 0 т2 0 т2 3 3 0 т2 Тз 0 0 Тз с С 0 Тз 0 т4 Тб т4 3 3 0 т4 Тб 0 0 т5 2 0 2 х Ь 0 0 0 Те С с 0 Тб 0 т4 т7 т7 2 2 0 т7 0 0 0 Рис. 7.11. Функции действия и перехода проц LR-АНАЛИЗ = 1. Пусть магазин МАГ2 пуст, СТРОКА содержит входную цепочку, а магазин МАГ1 — символ начального состояния; 2. ДЕЙСТВИЕ: Определяем цепочку а, состоящую из к очередных символов из СТРОКИ (или менее чем из к символов, если СТРОКА не содержит к символов); 3. Пусть D результат применения функции действия к состоянию, расположенному наверху МАГ 1, и к цепочке а; 4. выбор D из 5. Сдвиг: если СТРОКА не пуста то 6. переносим первый символ из СТРОКИ в МАГ2 7. иначе на 14 все;
568 Часть II. Применение графов и граф-моделей 8. Число I: если /— число символов в правой части правила с номером /, а А — левая часть этого правила 9. то удаляем по / символов из МАГ 1 и МАГ2, записываем А 10. в МАГ2 и переходим на 13 все; 11. Ошибка: Переходим на 14; 12. Допуск: Переходим на 15 все; 13. НОВОЕ СОСТОЯНИЕ: Применяем функцию состояния к символам, расположенным наверху МАГ1 и МАГ2; полученное состояние записываем в МАГ1 и переходим на ДЕЙСТВИЕ; 14. НЕУСПЕХ: стоп % Входная цепочка не является предложением % 15. УСПЕХ: стоп % Входная цепочка является предложением % все Если входная строка является предложением, то указанный анализатор проводит раз- бор снизу вверх, моделируя в обратном порядке ее правый вывод. Построение /.^-анализатора по некоторой грамматике, по существу, состоит в осуще- ствлении горизонтального движения одновременно по всем деревьям разбора всех предложений, заданных данной грамматикой. В этом случае, когда исходная грамма- тика является ЛЛ-грамматикой, такое движение позволяет выделить все возможные множества состояний, а также получить довольно простые правила движения по этим состояниям в зависимости от конкретного предложения. 7.4.11. Обработка синтаксических ошибок В большинстве трансляторов обнаружение и диагностика ошибок концентрируется вокруг синтаксического анализатора. Это связано, в первую очередь, с большой сте- пенью точности, которую можно достичь в синтаксическом определении языка про- граммирования с помощью КС-грамматики, а также возможностью по любой КС- грамматике автоматически строить распознаватель, допускающий в точности тот язык, который описывается данной грамматикой. Термин "синтаксическая ошибка" употребляется для обозначения ситуации, когда синтаксический анализатор попадает в конфигурацию, которая не является законной (допустимой) при разборе ни одной синтаксически правильной программы. В идеале обработка ошибки анализатором должна состоять в том, что он не только дает диаг- ностическое сообщение, но и нейтрализует ошибку: определяет ошибку и ее место- нахождение, исправляет ошибку, изменяет свою текущую конфигурацию и продол- жает разбор с тем, чтобы обнаружить и другие ошибки, имеющиеся в программе. Существующие подходы к обработке синтаксических ошибок лишь направлены на достижение этой цели и предполагают возобновление разбора после обнаружения ошибки, но заведомо не дают никакой гарантии, что ошибка будет успешно исправ- лена во всех ситуациях (исправление следует признать более успешным, если оно по отношению к другому исправлению позволит обнаружить в исходной програм-
Глава 7. Синтаксические деревья 569 ме больше ошибок и приведет к меньшему числу сообщений о несуществующих ошибках). Существует несколько простых стратегий нейтрализации ошибок, которые обычно применяются на практике. Режим переполоха Под режимом переполоха понимается следующая стратегия обработки анализатором недопустимого входного символа. Сначала анализатор игнорирует (пропускает) не- допустимый символ и все последующие символы, отличные от определенных, так называемых опорных, символов, как правило, являющихся ограничителями операто- ров (например, или служебное слово end являются опорными для языка Паскаль). Затем анализатор удаляет из стека все элементы до тех пор, пока не будет найден элемент, с которого анализатор может продолжить разбор, имея данный опорный символ на входе. Данная стратегия проста для реализации, не приводит никогда к зацикливанию ана- лизатора, но имеет серьезный недостаток, заключающийся в том, что игнорируемые (не анализируемые) последовательности входных символов могут быть достаточно большой длины. Исключение символов Некоторой модификацией описанного метода переполоха является простое (без из- менения стека) игнорирование недопустимых входных символов до тех пор, пока не встретится допустимый. Хотя можно привести много ситуаций, когда такая стратегия дает хорошие результаты (например, в строке X := 3+Y+Z) * (W+V) программы для язы- ка Паскаль, в которой закрывающая скобка является недопустимым символом), тем не менее ее следует применять с осторожностью (по крайней мере, не игнорируя при этом опорных символов). Вставка символов В ряде случаев оправдано исправление входной программы путем вставки некоторо- го символа перед текущим недопустимым символом. Например, последовательность end begin всегда является недопустимой для языка Паскаль, и включение между служебными словами end и begin точки с запятой следует признать идеальным ис- правлением этой ошибки. Следует отметить, что в отличие от предыдущих стратегий вставка символов, если она никак не ограничивается, может привести к зацикливанию анализатора. Правила для ошибок Стратегия нейтрализации очень часто встречающихся ошибок может состоять в рас- ширении синтаксического определения языка программирования за счет включения в него программ, содержащих данные ошибки. При таком подходе обработка соответ- ствующих ошибок переносится на анализатор в трансдукторы (генерационные про- цедуры) при тех синтаксических правилах, которые включены в грамматику для
570 Часть II. Применение графов и граф-моделей описания программ с ошибками. Такая стратегия является идеальной для таких оши- бок, как, например, использование в языке Алгол-68 точки с запятой перед end. При применении данной стратегии следует следить за тем, чтобы грамматика при расширении оставалась однозначной. Можно указать только два вида обнаружения ошибки в анализаторе простого пред- шествования: отсутствие отношения предшествования между символом, находящим- ся наверху стека, и текущим входным символом; основа выделена, но нет правила, для которого она является правой частью. Обработка ошибок второго вида обычно осуществляется по правилам минимальной коррекции: среди правил ищется то, которое является ближайшим к выделенной ос- нове. При нейтрализации ошибок первого вида требуется осуществить одно из обыч- ных действий: изменение символов, вставку символов во входную цепочку или стек, удаление символов из входной цепочки или стека. Эти действия (подпрограммы) по обработке ошибок должны быть заранее выбраны и указаны для всех незаполненных элементов матрицы предшествования (причем для разных элементов может исполь- зоваться одна и та же подпрограмма). Например, пусть между символом в стеке b и текущим входным символом с нет от- ношения предшествования. Тогда возможные решения (а— символ в стеке, находя- щийся под b, ad— входной символ, следующий за а): □ если а < с (т. е. а < с или а = с), то можно удалить Ь из стека; П если Ъ < d, то можно удалить с из входной цепочки; □ если найдется такой символ h, что b < h и h < с, то символ h можно поместить перед с. Любое из этих решений приводит к конфигурации с отношением предшествования для входного символа, что гарантирует конечность работы анализатора, несмотря на изменения и вставки символов, осуществляемые им при нейтрализации ошибок. В отличие от анализатора предшествования LL- и /./^-анализаторы обладают важным свойством правильности прочитанного префикса входной цепочки — они обнаружи- вают ошибку сразу же, на первом символе, который не должен следовать за обрабо- танной к этому времени частью входной цепочки Следует, однако, заметить, что, хотя это свойство позволяет как можно раньше обнаружить наличие ошибки, тем не менее оно не гарантирует обнаружения ошибки в том месте, где она реально была допущена в программе. Проектирование подпрограмм обработки ошибок в этих анализаторах требует иссле- дования всех входов в таблицу, связанных с ошибками, и выделения для каждого из них тех наиболее вероятных программистских ошибок, которые проявляются в этой ошибке при работе анализатора. Следует отметить и альтернативный подход к обработке ошибок, который состоит в реализации некоторого систематического способа их нейтрализации. Например, в /./.-анализаторе может быть реализовано исправление ошибок на основе режима переполоха следующим образом. При встрече недопустимого символа в анализаторе
Глава 7. Синтаксические деревья 571 последовательно выполняются следующие действия: удаляются из входной цепочки все символы до первого опорного: происходит удаление символов из стека до тех пор, пока не встретится символ А, из которого выводится данный опорный символ; если А не совпадает с опорным, то производится вывод из А и символы предопреде- ленным образом помещаются в стек до тех пор, пока нужный опорный символ не окажется вверху стека. После выполнения этих действий возобновляется нормальная работа анализатора. 7.5. Перевод и конструкторы анализаторов Процесс трансляции естественным образом разбивается на последовательность эта- пов трансляции, включающую лексический, синтаксический, контекстный анализ и генерацию. Каждый из этих этапов определяет некоторый перевод (отношение между цепочками), а композиция всех этапов определяет перевод, образуемый парами: ис- ходная программа, объектная программа. Если не особенно стремиться к эффектив- ности, то некоторые из этапов трансляции можно рассматривать как отдельные про- межуточные трансляторы, реализующие связанные с ними переводы независимо, без объединения функций различных этапов на одном просмотре представления трансли- руемой программы. 7.5.1. Понятие перевода, СУ-схемы и преобразователя Проблема задания конечными средствами бесконечного множества пар, образующих перевод, аналогична проблеме задания бесконечного языка. Для определения перево- да можно использовать грамматику, снабдив ее механизмом, обеспечивающим выход для каждой порождаемой цепочки, или расширить возможности распознавателя, по- зволив ему выдавать на каждом такте цепочку выходных символов. Пусть Е— входной алфавит и А— выходной алфавит. Переводом с языка А|сГна язык Z,2 £ Л* называется отношение Т из Е* в А*, для которого Ly — область опреде- ления, a Z-2— множество значений. Если (а, 0) е Т, то цепочка 0 называется выходом для цепочки а, а цепочка a— входом для цепочки 0. Перевод, предназначенный для описания языка программирования, является функцией, т. е. для каждого входа име- ется не более одного выхода. Примером перевода, реализуемого почти в любом трансляторе, является отображение обычной (инфиксной) записи арифметических выражений в префиксную и/или пост- фиксную запись. Схема синтаксически управляемого перевода (сокращенно СУ-схема) представляет собой грамматику, в которой к каждому правилу присоединяется элемент перевода. Предполагается, что всякий раз, когда правило участвует в выходе входной цепочки, элемент перевода используется для вычисления той части выходной цепочки, которая соответствует порожденной этим правилом части входной цепочки.
572 Часть II. Применение графов и граф-моделей Более точно, СУ-схема Т— это пятерка (1У, Z, Д, R, Е), где W— алфавит нетермина- лов, Е — начальный символ, a R — конечное множество правил вида А —» а, 0, где А е W, а е (2 и И7)*, 0 е (X и Л)’ и вхождения нетерминалов в цепочку 0 образуют перестановку вхождений нетерминалов в цепочку а. Пусть А —» а, 0 — правило. Ка- ждому вхождению нетерминала в цепочку а соответствует некоторое вхождение того же нетерминала в цепочку 0. СУ-схема Т называется простой, если для каждого пра- вила А —> а, 0, из Т соответствующие друг другу вхождения нетерминалов встреча- ются в а и 0 в одном и том же порядке. Определим множество выводимых пар цепочек схемы Т по следующим правилам: (£, £) — выводимая пара, в которой вхождения символа Е соответствуют друг другу; если (о.Л0, уЯсо)— выводимая пара, в которой два выделенных вхождения нетерми- нала А соответствуют друг другу, и А -> 5, т] е Т, то (а80, утусо) — выводимая пара, в которой соответствие вхождений нетерминалов определяется их соответствием в паре (аА0, уЛсо) и в правиле А —> 8, ту. Переводом, определяемым схемой Т(обознача- ется г(7)), называют множество таких выводимых пар (а, 0), что а е £' и 0 е Д*. Рассмотрим язык арифметических выражений А(Г0), введенный в разд. 7.2.3. Сле- дующая простая СУ-схема отображает арифметические выражения из языка £(Г(1) в соответствующие постфиксные польские записй: Е-*Е+Т, ЕТ+, Е->Т,Т, Т-> T*F, TF*, Т-> F, F, F(Е), Е, F а, а. Например, можно рассмотреть следующую последовательность выводимых пар данной СУ-схемы: (£, £), (£+7, ЕТ+), (Т+Т, TT+),(F+T, FT+). (а+Т, аТ+), (а+Т * F, aTF*+), (a+F* F, aFF*+),(a + a* F, aaF*+), (a + a* a, aaa*+). Преобразователи — это распознаватели, которые дополняются выходной лентой и на каждом шаге распознавания могут выдавать на выходную ленту цепочки выходных символов ограниченной длины. В качестве примера рассмотрим МП-преобразователь (МП-распознаватель с выхо- дом), осуществляющий перевод арифметических выражений из языка £(Г0) в соот- ветствующие префиксные записи. Он имеет набор команд, получающийся из сле- дующих схем команд: (А, Ь,Н)-> {(О, С, ЕН, е)}, (С, Ь,Е)-> {(О, С, Е + Т, +), (О, С, Т, е)}, (С, Ь,Т)-> {(О, С, T*F, *), (О, С, F, е)}, (С, b,F)-> {(О, С, (£), е), (О, С, а, е)},
Глава 7. Синтаксические деревья 573 (C,d,d)-+{(\,C,e, е)}, (С, а, а)-> {(1,С, е, а)}, (С, В, Н)-> {(О, D, е, е)}, всевозможными заменами b на символы из {а, +, *, (,)} и d на символы из {+, *, (,)}. В МП-нреобразователе А — это начальное состояние, {D} — множество заключи- тельных состояний, а последний элемент в четверке правой части правила — это строка, печатаемая на входную ленту. Для входной строки а + а * а возможна сле- дующая последовательность конфигураций: (Я, а + а * а, Н, е), (С, а + а * а, ЕН, е), (С, а + а * а, Е + TH, +), (С, а + а * а, а + TH, +), (С, а * а, + TH, +а), (С, а * а, TH, +а), (С, а * а, Т * FH, +а*), (С, a* a, F * FH, +а *), (С, а * а, а * FH, +а, *), (С, * а, * FH, + * а), (С, a, FH, +а * а), (С, а, аН, +а * а), (С, е, Н, +а * аа), (D, е, е, +а * аа). 7.5.2. Конструктор лексических анализаторов Удобной моделью лексического анализатора служит набор конечных преобразовате- лей, работающих последовательно или параллельно. Эти преобразователи могут строиться автоматически по регулярным выражениям, описывающим лексемы. Язык регулярных выражений. Регулярные выражения определяют в точности тот класс языков (получивший название регулярных множеств), который задается грам- матиками типа 3 или конечными автоматами, но являются более удобным способом описания лексем Регулярные выражения в алфавите S и множества цепочек, ими образуемых, опреде- ляются рекурсивно следующим образом: П 0 — регулярное выражение, обозначающее пустое множество; П е—регулярное выражение, обозначающее множество {е}; □ если а е S, то а — регулярное выражение, обозначающее множество {а}; □ если р и q — регулярные выражения, обозначающие множества Р и Q, то (p\q), pq и (р)* —также регулярные выражения, обозначающие соответственно множества Р kj Q, PQ и Р\ Для некоторых интересных с практической точки зрения регулярных множеств (на- пример, конечных, но достаточно больших множеств, в частности для множества идентификаторов языка Фортран) регулярные выражения оказываются чересчур гро- моздкими, и поэтому удобного описания таких множеств часто используются расши- рения языка регулярных выражений, состоящие в следующем. Если р и q - некото-
574 Часть II. Применение графов и граф-моделей рые регулярные выражения или расширенные регулярные выражения, обозначающие множества Р и Q, то (р)+, (р)+и, (р)*", (р-q) и (рп<?) являются расширенными регу- лярными выражениями, которые обозначают регулярные множества РР*, Р Р2 и.. u Р", {е} u Р и ... v Р”, Р — Q, Р r\Q соответственно. Используются также имена (нетерминалы) при описании одних регулярных множеств в терминах других, но при этом следят за тем, чтобы определения, в которых участ- вуют имена, не приводили к порочному кругу, т. е. чтобы не получалась, по существу, грамматика, не принадлежащая типу 3. Кроме того, обычно устраняются лишние скобки там, где это не может привести к недоразумениям. Например, общепринятый вид записи вещественных констант (без ограничения на длину и величину констант) может быть задан следующей последовательностью ре- гулярных определений: цифра = (0|1|2|3|4|5|6|7|8|9) знак = (+1 -1 е) целое = знак (цифра)+ десятичное = знак ((цифра)*, (цифра)+ |(цифра)+ . (цифра)*) константа = (целое | десятичное | десятичное Е целое). Непрямой лексический анализ При непрямом лексическом анализе сканер должен по типу лексемы определить, по- явилась ли подцепочка, образующая лексему данного типа. Конечный преобразова- тель, осуществляющий это действие,— почти конечный автомат, поскольку он чита- ет вход, не производя выхода, до тех пор, пока не обнаружит присутствия лексемы данного типа, достигнув заключительного состояния. Тогда он сигнализирует о появлении нужной лексемы и выдает на выход образующих ее цепочку символов. Поэтому проблема построения непрямого сканера, по существу является проблемой построения по заданному регулярному выражению конечного автомата и его про- граммной реализации. Обычно такое построение происходит в два этапа: на первом этапе осуществляется переход от регулярного выражения к недетерминированному конечному автомату, а затем либо преобразуют этот автомат в детерминированный, либо моделируют его работу, прослеживая параллельно всевозможные последова- тельности тактов. Эти этапы достаточно просты, если для описания лексем не используются операции пересечения и вычитания, допустимые в расширенных регулярных выражениях. Прямой лексический анализ При прямом лексическом анализе требуется найти одну из многих лексем. Таким об- разом, моделью прямого анализатора является конечный преобразователь, модели- рующий много конечных автоматов и сигнализирующий о том, какой из них распо- знал входную цепочку. Построение прямого сканера обычно осуществляется путем объединения недетерми- нированных автоматов, распознающих разные лексемы, с последующей детермини-
Глава 7. Синтаксические деревья 575 зацией объединенного недетерминированного автомата. Объединенный детермини- рованный автомат является конечным преобразователем простого типа, который вы- дает имя обнаруженной лексемы и, возможно, информацию, локализующую ее вхож- дение. Обнаруженная лексема выдается в том случае, если объединенный автомат попадает в состояние, образованное из заключительного состояния одного из состав- ляющих автоматов и не содержащего никаких других состояний. Однако не всегда удобно объединенный преобразователь составлять из автоматов, определяющих лексемы каждого типа. Например, если в языке есть ключевые слова, то нецелесообразно строить отдельный автомат для определения любого идентифи- катора, отличного от ключевых слов, поскольку такое определение сложно и требует много состояний. Вместо этого эффективнее пользоваться определением идентифи- катора и предоставлять объединенному автомату возможность найти правильное ре- шение. В этом случае объединенный автомат выдает ключевое слово в том случае, когда он попадает в состояние одного из автоматов, соответствующих ключевым словам, и в состояние автомата, соответствующее идентификаторам, а следующий входной символ (это может быть пробел или специальный знак) указывает на окон- чание лексемы. 7.5.3. Конструкторы синтаксических анализаторов Подобно лексическому анализу синтаксический анализ поддается автоматизации. По любой совокупности синтаксических правил можно автоматически (с помощью неко- торого универсального конструктора) построить синтаксический анализатор, который будет определять, имеет ли входная программа синтаксическую структуру, опреде- ляемую правилами. Однако, с одной стороны, любой универсальный конструктор анализаторов не сможет во всех нужных случаях строить достаточно эффективные трансляторы, а с другой — синтаксические структуры языков программирования дос- таточно просты и естественно выражаются в терминах более узких классов грамма- тик, чем класс всех грамматик. Поэтому на практике обычно используются конструк- торы, области применения которых ограничены некоторыми подмножествами КС- грамматик, как правило, LL- или £/?-грамматиками. Такие конструкторы не только строят эффективные трансляторы для широких классов языков, но и позволяют пре- дусмотреть удовлетворительные методы обработки синтаксических ошибок. Например, построение анализатора для грамматики простого предшествования сво- дится к определению по грамматике простого предшествования Г отношений между символами грамматики. Это вычисление осуществляется простым алгоритмом, ис- пользующим следующие свойства отношений предшествования для любых А" и У из И'иУ: □ X < Y тогда и только тогда, когда в Г есть правило А —> аА7?Р и В =>+ Уу; □ X = К тогда и только тогда, когда в Г есть правило А —> осЛУР; □ X > Y тогда и только тогда, когда Y е S и в Г есть такое правило А —> а£>Ср, что В^ХнС=> Гт.
576 Часть II. Применение графов и граф-моделей 7.5.4. Конструктор LL-преобразователя Определим более точно МП-преобразователь, который мы хотим построить для лю- бой ££-грамматики. Он должен реализовать перевод {(а, 1\12 ... £) ' а е £(Г), a /|/2... ir— цепочка номеров правил грамматики, выписанных в порядке их примене- ния в левом выводе цепочки а}. Например, для грамматики Г| с правилами Е -> аАЕ, Е-+Ь, А -> а, А -> ЬЕА, которая, как нетрудно увидеть, является ££(1)-грамматикой, элементом перевода бу- дет пара (abbab, 14232). Легко заметить, что цепочка номеров правил, построенных преобразователем, одно- значно определяет соответствующее дерево разбора. Предполагается, что преобразователь использует входную ленту, магазин и выход- ную ленту. Конфигурацию преобразователя будем представлять в виде тройки (а, Х$Н, у), где а — неиспользованная часть входной цепочки, Х$Н — цепочка в магази- не {X— верхний символ, а Н— специальный символ, применяемый в качестве дна магазина) и у— цепочка на выходной ленте. Через М будем обозначать алфавит ма- газинных символов без символа Н. Работой преобразователя руководит управляющая таблица Т, задающая отображение (М о {Н} х Е*)* в множество, в которое входят: значения УСПЕХ; НЕУСПЕХ; СДВИГ; пары (a, /), где а е Л/, I — номер правила (предполагается, что а — это ли- бо правая часть z-го правила, либо некоторое его представление). При этом считается, что Т(Н, е) = УСПЕХ. Работа преобразователя происходит в соответствии со следующими тремя правилами. Если возникает конфигурация (е, Н, л), то работа преобразователя успешно заверша- ется ил — его выход. Пусть (а, Х0, л) — текущая конфигурация и о-А-префикс входной цепочки а. Тогда: □ если Т(Х, и) = НЕУСПЕХ, то разбор прекращается и выдается сообщение об ошибке; □ если Т(Х, со) = СДВИГ, то происходит переход к конфигурации (у, 0, л), где а = Ху; □ если Т(Х, со) = (8, /), то происходит переход к конфигурации (а, 80, у /)• Работа преобразователя начинается с конфигурации (т, ЕН, е), где т — входная це- почка. Например, для ££(1)-грамматики Г, управляющая таблица преобразователя изобра- жена на рис. 7.12.
Глава 7. Синтаксические деревья 577 Префикс входной цепочки Л а b е Е аАЕ, 1 Ь, 2 ОШИБКА Верхний А а, 3 ВЕА, 4 ОШИБКА символ А СДВИГ ОШИБКА ОШИБКА магазина В ОШИБКА СДВИГ ОШИБКА Н ОШИБКА ОШИБКА УСПЕХ Рис. 7.12. Таблица преобразователя В соответствии с ней возможна следующая последовательность конфигураций: (abbab, ЕН, е), (abbab, aAEH, 1), (bbab, ЬЕАЕН, 14), (bab, ЕАЕН, 14), (bab, ЬАЕН, 142), (ab, АЕН, 142), (ab, aEH, 1423), (b, EH, 1423), (b, bH, 14232), (e, H, 14232). Таким образом, задача построения по ££(А)-грамматике Г соответствующего преоб- разователя состоит в построении управляющей таблицы Т нужного вида. Введем следующие обозначения. Цепочка а является A-префиксом цепочки 0, если либо |0| < к и а = 0, либо |0 | > к и ау = 0 для некоторой цепочки у. Для любых Li, £2£ Е* множество A-префиксов всех цепочек из L\, L2 обозначим через L\ Ф Ь2. Для любой ае обозначим через ПЕРВ(а) множество A-префиксов всех терми- нальных цепочек, выводимых из а. Если из а выводима пустая цепочка, то считается, что ПЕРВ(а) содержит е. Для любых А е И'и рассмотрим таблицу Ta,l, которая каждой цепочке а е 1 сопоставляет либо символ ОШИБКА, если в Г нет такого правила А р, что а е ПЕРВ(р) Ф L, либо пару (А —> 0, У), где А —> 0 — единственное правило из Г, для которого а е ПЕРВ (0) ®£, a Y определяется следующим образом: □ если 0 = OQ)X| О|Л2... А,„а„„ где m > О, А, е IV и a, е Е*, то Y = <УЬ .... Y„, ), где У, = ПЕРВ(а, А,+1 а,+|... А,„а„,) Ф £; □ если 0 е X*, то У— пустое множество. Содержательно это означает следующее: если 7\/.(а) = ОШИБКА, то в Г невозможен вывод вида Лео =>+ ау для со е L и у е Е‘; если ТА1{а) = (А -> 0, (Уь ..., Y„,)), то най- дется в точности одно правило А —> 0, которое можно применить на первом шаге вывода Лео =>+ ау для со е L и у е Е", а каждое множество У, дает всевозможные A-префиксы, которые могут в дальнейшем при выводе следовать за подцепочкой, выводимой из А,. Заметим, что ТА /,(а) всегда определена в силу того, что Г является ££(А)-грам м эти ко й. 19 Зак. 202
578 Часть II. Применение графов и граф-моделей В качестве примера рассмотрим ££(2)-грамматику Г2 с правилами (Е —> aEaaa | bAba, А —> £| е}. Значения элементов таблицы отличные от значения ОШИБКА, при- ведены на рис. 7.13. В качестве магазинных нетерминальных символов преобразователя для грамматики Г рассматривается множество таблиц ./, которое строится по следующим правилам: в пустое множество ./ включается таблица //,{<.;; если некоторая таблица из ./ имеет значением (А -> а^А, а,... А,„а„„ (Уь ..., К„, » и ./ не содержит таблицы 7>, г„ то TAiri включается в J. Нетрудно заметить, что это множество таблиц для грамматики Г2 будет состоять из трех элементов, приведенных на рис. 7.13 и обозначенных через То, 7} и Т2. а Те. {е) (а) аа (Е -> аАаа, <{аа}>) ab (Е -»аАаа, <{аа}>) bb (Е-> ЬАЬа, <{Ьа}>) а Гд,{аа)(а) Ьа (А ->Ь, 0) аа (А ->е, 0) а Та {ьа}(а) Ьа (А-> е, 0) ЬЬ (А-> Ь, 0) Рис. 7.13. Множество таблиц для Г2 Множество ./и £ и {//} является магазинным алфавитом преобразователя для грам- матики Г, таблица 7л(е( — начальным состоянием, а для любых магазинного символа X и цепочки р е значение Т(Х, р) определяется по следующим правилам: □ если Х = ТА ,. и 7>,л(Р) = (Л —> а0 А^... А„, а„„ <ГЬ ..., Г,„ », то Т(Х, р) = (cq, TAli п «I... rm а„„ [), где I —- номер правила Л -э а0 Л|«|... Л,„ а,,;, □ если Х= Н и Р = е, то Т(Х, Р) = УСПЕХ; □ если X е £ и Р = Ха, то Т\Х, Р) = СДВИГ; П в остальных случаях Т(Х, Р) = ОШИБКА. Например, для /,£(2)-грамматики Г2 рассмотренный конструктор построит управ- ляющую таблицу, изображенную на рис. 7 14 Число шагов, выполняемых преобразователем с управляющей таблицей, построенной описанным конструктором по /./.-грамматике, линейно зависит от длины входной цепочки. Важным частным случаем LL-грамматик являются /£(1)-грамматики. Пусть Г яв- ляется /£(1)-грамматикой и для любого А е W определено множество СЛЕД(Л) = = {а : Е =>’ осЛ р и а <= ПЕРВ(Р)}. Управляющая таблица преобразователя для Г мо-
Глава 7. Синтаксические деревья 579 жет быть построена следующим образом. Множество IV vj £ и {Н} образует алфавит магазинных символов, Е— начальное состояние, а для любых X е (Ж uZu {//}) и a е (Е и {е}) значение Т(Х, а) определяется по следующим правилам: если х —> а — правило из Г с номером i и либо а е ПЕРВ(сс), либо е е ПЕРВ(ос) и а е СЛЕД(а), то Т(Х, а) = (а, /); если Х=Н и а = е, то Т(Х, а) = УСПЕХ, если Х~а, то Т(Х, а) = СДВИГ; в остальных случаях Т(Х, а) = ОШИБКА. аа Ab а ba Bb be То aTiaa, 1 аТаа, 1 О О ВТ2Ьа, 2 О О Г, е, 4 О О ь, з О О О Т2 О О О е, 4 Ь, 3 О О А С С С О О О О В О О О С С с О Н О О О О О О У Рис. 7.14. Управляющая таблица для грамматики Гг: О — ОШИБКА, С — СДВИГ, а У — УСПЕХ Для уменьшения размера таблиц для LL(] ^распознавателя обычно применяются сле- дующие два метода- обработка правила Л -> аа и входного символа а реализуется загрузкой а в магазин и сдвигом входа на один символ, что позволяет уменьшить ма- газинный алфавит; используется один терминал с "индикатором" для нескольких не- терминалов с одинаковыми действиями разбора. 7.5.5. Конструктор L/7-преобразователя ЩА)-анализатор достаточно подробно описан в разд. 7.4.10. В отличие от него пре- образователь, конструир^ЗДйяй описываемым конструктором, содержит выходную ленту и при выполненй^шаН с именем ЧИСЛО/ дополнительно осуществляет запись на выходную ленту Рассмотрим^ р^оту преобразователя такого вида для пополненной грамматики Г3, приведен'ншИхразд. 7.4.10, с использованием функций действия и перехода, описан- ных таяиЙе. В результате обработки входа aabb на выходе этого преобразователя бу- д£гjjoynefia цепочка 33322, однозначно определяющая правый вывод цепочки aabb в исхбдаой грамматике. Магазинными символами будут множества ГА(А)-ситуаций для Г (или просто ситуа- ций), каждая из которых имеет вид [Л —> р • у, а], где а е , Л —> Ру— правило из Г. Причем будут рассматриваться только ситуации [А -> Р • у, а], для которых су- ществует такой правый вывод Е =>* (вА 5 => «>Ру5, что а е ПЕРВ(5) и <х>Р — активный префикс некоторой правовыводимой цепочки, т. е. он не выходит за правый конец ее основы (такая ситуация называется допустимой для а>Р).
580 Часть II. Применение графов и граф-моделей Алфавит магазинных символов F состоит из множества ситуаций F(y) для активных префиксов у грамматики Г. Рассмотрим метод построения F(y) для некоторого у = Х\Х2...Х„ как объединение множеств F(e), F(vV|), F(XtX2), F(XtX2 ...Х„). F(e) — это минимальное множество ситуаций, содержащее [Е -> а, е] для любого правила Е —> а из Г и удовлетворяю- щее следующему свойству: если F(e) содержит ситуацию [А —> В а, 0] и В —> 5 правило грамматики, то любая ситуация [В -у 8, со], где <о е ПЕРВ(а0), также содер- жится в F(e). Для каждого I < п множество (F(X}X2 — X,) равно ШАГ^А, Az2 --X-i), X,), где F2 = ШЛГ(^|, X) — минимальное множество, удовлетворяющее следующим свойствам: если [А —> а АЗ, 0] е Fh то F2 содержит состояние [А -> а. X 8, 0]; если [А -> а В 6, 0] е Ft и F —> 8— правило грамматики, то F, содержит ситуацию [В —> • 8, со] для каждой цепочки со е ПЕРВ(80). Например, для LL( 1 )-грамматики Г3 имеем F(e) = {[£ ->• S, е], [£ SaSb, е], [£->• SaSb, а], [.S'->• е, е], [5 —> е, а]}, F(S) = {[£ S-, е], [S -> S aSb, е], [5-> S •«.%, с/]}, F(Sa) = {[.S' SaSb, е], [5 -> SaSb. а]. [S -> SaSb, а]. [S-> SaSb, В], [Е-> е-, я], [£-> е, 6]}. Таким образом, построение F(y) связано с горизонтальным движением по всем де- ревьям разбора таких правовыводимых цепочек, для которых у является активным префиксом. Это множество содержит всю информацию, необходимую для продолже- ния разбора любой правовыводимой цепочки, для которой у — активный префикс. Так как грамматика Г содержит конечное множество правил, число множеств ситуа- ций в F тоже конечно, но часто бывает очень большим. Построение F может быть осуществлено по следующим правилам: включить То = .F($^ пустое множество Ей считать его необработанным; осуществить обработку ка>^ого,^робработанного Т, из F, вычисляя Tj = ШАГ(7’„ X) для каждого А' е (IF u S) и включдр 3\в качестве необра- ботанного множества в F, если Д не пусто и еще не содержится в F. Например, для LL( I )-грамматики Г3 получаем То = F(e), 7\ = ШАГ(Г0, Е) = lb А Г( Т0,а) = = ШАГ(Г0, Ь) = 0,Т2 = ШАГ(Г,, а) = F(Sa), ШАГ(Г,, Е) = ШАГ(Г,, Ь) -Л^/кром? ft, Д и Тт, в F попадают также множества Т3 = {[.S' —> Sa Sb, е], [.S’ —> SaS b, ст], [E —> [E -> S • aSb, fe]}; T4 = {[5-> Sa Sb, a], [S-+Sa- Sb, 6], [E -> SaSb, a], [5-> • Saty *], [S-> • e, a], [S-> e, *]}; T5 = {[S-> SaSb , b], [S^ SaSb , «]}; T6 = {[S SaS b, a], [S-> SaS b, b\, [5-> S • aSb, a\, [S-► .S’ aSb, fe]}; T7 = {[S-э SaSb , «], [S -> SaSb -, fe]}. После того как F найдено, можно осуществить вычисления функций действия/и пе- рехода g, используемых в ЛЕ(А)-распознавателе. Для любого Т,е. F и a е X* значение Д Тп а) определяется по следующим правилам: если Tj содержит такое состояние [А —> 0 • у, со], что у — не пустая цепочка и а явля-
Гпава 7. Синтаксические деревья 581 ется ^-префиксом некоторой правовыводимой из усо цепочки aS (т. е. а е ПЕРВ(ую)), на последнем шаге вывода которой не применяется е-правило, то _/(/], а) = СДВИГ; если Т} содержит состояние [Л —> 0, е] и Л —> 0 имеет номер I, то f (Г,, а) = ЧИСЛО/; если Tj содержит состояние [£ -» 0, е], и a = е, то f (Tt, а) = ДОПУСК; в остальных случаях///^, а) = ОШИБКА. Для любых Д е F и X е (S vj IV) значение g(Tj, X) равно ШАГ(Д, А), если множество ШАГ(Д, X) не пусто, и равно ОШИБКА в остальных случаях. Если вычислять функции f и g по описанным правилам для грамматики Г3, то ре- зультатом этого вычисления будут соответствующие функции, приведенные в разд. 7.3.10. Число шагов, выполненных преобразователем, построенным описанным LR-koh- структором, линейно зависит от длины входной цепочки. Описанный конструктор строит так называемый канонический /.//-анализатор. Суще- ствуют конструкторы, которые могут построить /.//-анализаторы меньшего объема, однако важным свойством канонического анализатора является его способность объ- являть об ошибке при первой же возможности в ходе считывания входной цепочки слева направо. 7.5.6. Использование конструкторов Каждый из описанных конструкторов может быть расширен таким образом, чтобы он проверял принадлежность входной грамматики соответствующему классу грамматик. Грамматики простого предшествования— один из первых методов, используемых в трансляторах для эффективного синтаксического анализа. Однако, как правило, реальные языки программирования если и описываются этими грамматиками, то тре- буют для своего описания серьезных преобразований исходной грамматики Кроме того, анализатор простого предшествования уступает LL- и /.//-анализаторам в смыс- ле ранней диагностики ошибок, а также простоты модификации при изменении язы- ка. Поэтому конструкторы для грамматик простого предшествования используются достаточно редко. Объем работы конструктора для £//-грамматик резко возрастает с увеличением раз- мера грамматики и ростом к Для реальных грамматик объем этих вычислений часто оказывается неприемлемо большим даже при к = 1. Поэтому обычно на практике ис- пользуются конструкторы для некоторых подклассов /.//-грамматик, которые строят, например, SLR( 1 )-анализаторы или LALR( 1)-анализаторы. Наиболее широко используется конструктор LL{ 1 )-анализаторов, которые достаточно мошны, выразительны, эффективны и достаточно естественно согласуются с другими этапами трансляции. Как правило, если исходная грамматика языка программирова- ния не является /./.(Г)-грамматикой, то она может быть преобразована в ££(!)- грамматику с помощью преобразований "добавление нетерминала" и "изменение на- правления рекурсии".
582 Часть II. Применение графов и граф-моделей Библиографический комментарий Синтаксическому описанию и анализу языков программирования посвящена обширная лите- ратура, в том числе монографического плана [1—29]. Книги [3—14] систематизируют значи- тельную часть результатов, касающихся этих вопросов, и могут быть рекомендованы как ос- новная литература для обстоятельного и глубокого изучения предмета. Основой для данной главы послужил материал монографий [10, 12]. Список литературы 1. Агафонов В. Н. Синтаксический анализ языков программирования. — Новосибирск: Изд- во Новосиб. ун-та, 1981. 2. АЛГОЛ-68. Методы реализации / Под ред. Г. С. Цейтина. — Л.: Изд-во Ленингр. ун-та, 1976. 3. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции. — М.: Мир, 1978,—Т. 1,2. 4. Болье Л. Методы построения компиляторов // Языки программирования.— М.: Мир, 1972. 5. Братчиков И. А. Синтаксис языков программирования. — М.: Наука, 1975. 6. Гинзбург С. Математическая теория контекстно-свободных языков. — М.: Мир, 1970. 7. Гладкий А. В. Формальные грамматики и языки. — М.: Наука, 1973. 8. Глушков В. М., Цейтлин Г. Е., Ющенко Е. Л. Алгебра. Языки. Программирование. — Ки- ев: Наук, думка, 1989. 9. ГрисД. Конструирование компиляторов для цифровых вычислительных машин.— М.: Мир. 1975. 10. Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки деревьев. — Ново- сибирск: Наука, 1994. 11. Касьянов В. Н. Лекции по теории формальных языков, автоматов и сложности вычисле- ния. — Новосибирск: Изд-во Новосиб. ун-та, 1995. 12. Касьянов В. Н., Поттосин И. В. Методы построения транслязоров. — Новосибирск: Нау- ка. Сиб. отд-ние, 1986. 13. Льюис Ф., Розенкранц Д., Стирнз Р. Теоретические основы построения трансляторов.— М.: Мир, 1979. 14. Маккиман У., Хорнинг Дж., Уортман Д. Генератор компиляторов.— М.: Статистика, 1980. 15. Меристе М. Б. Методы реализации атрибутных схем в системах построения транслято- ров // Программирование. — 1980. —№5. — С. 40—49. 16. Параметрические транслирующие системы/ М. Г. Гонца, М. Н. Маричук, Г. А. Бостан, Г. А. Магариу. — Кишинев: Штиинца. — 1974. — Т. 1,2. 17. Пеньям Я. Э. Синтез грамматического процессора по атрибутной грамматике // Програм- мирование. — 1983. — № 1. — С. 50—60. 18. Семантика языков программирования. Сб. статей. / Под ред. В. М. Курочкина.— М.: Мир, 1980.
Глава 7. Синтаксические деревья 583 19. Трахтенгерц Э. А. Введение в теорию анализа и распараллеливания программ ЭВМ в про- цессе трансляции. — М.: Наука, 1981. 20. Труды Всесоюзного симпозиума по методам реализации алгоритмических языков. — Но- восибирск, 1975. — Ч. 1,11. 21. Фельдман Дж., Грис Д. Системы построения трансляторов И Алгоритмические языки/ ВЦ АН СССР. — М„ 1971. —Вып. 5. — С. 105—214. 22. Фишер Ф. П., Суиндл Д. Ф. Системы программирования. — М.: Статистика, 1971 23. Фуксман А. Л. и др. Основы разработки трансляторов. — Ростов н/Д: Изд-во Ростов, ун-та, 1974. 24. Хантер Р. Проектирование и конструирование компиляторов. — М : Финансы и статисти- ка, 1984. 25. Хопгуд Ф. Методы компиляции. — М.: Мир, 1972. 26. Graham S. L., Harrison М. A., Ruzzo W. L. An improved context-free recognizer // ACM. Trans. Program Languages Systems. — 1980. — Vol. 2, N 3. — P. 415—462. 27. Nijholt A. Parsing strategies: a concise survey // Leet. Notes Comput. Sci.— 1981 — Vol. 118, —P. 103—120. 28. Rieks op den Akker. On LC(O) grammars and languages // Theor. Comput. Sci.— 1989.— Vol. 66, N 1, —P. 65—85. 29. Seite B. A YACC extension for LR grammar parsing // Theor. Comput. Sci.— 1987.— Vol. 52, N 1, —P. 91—143.
ГЛАВА 8 Контекстный анализ Завершающим в построении абстрактной программы по исходному тексту в процессе трансляции является этап контекстного анализа, который приписывает вершинам дерева разбора значения всех так называемых статических атрибутов и тем самым осуществляет построение атрибутного дерева транслируемой программы. Атрибуты вершин дерева кодируют ту часть синтаксических свойств транслируемой програм- мы, которые не описываются КС-грамматикой (например, такой атрибут, как класс конструкции, связанной с идентификатором), а также ряд других (семантических) ее свойств, позволяющих осуществлять построение выходной программы (на этапе ге- нерации) при систематическом обходе дерева разбора и за счет вызовов генерацион- ных процедур (трансдукторов), обрабатывающих вершины дерева вместе с их атри- бутами и соответствующих понятиям и лексемам языка. Формальное описание ука- занных свойств языка осуществляется с помощью так называемых атрибутных грамматик. 8.1. Задача контекстного анализа Выходом синтаксического анализа является представление программы в виде дерева разбора, описывающего иерархическое строение составляющих ее понятий и лексем. Дальнейшая задача трансляции — снабдить вершины этого дерева соответствующи- ми атрибутами. Процесс построения атрибутного дерева путем определения значе- ний атрибутов у вершин дерева разбора называется контекстным (или семантиче- ским) анализом. С логической точки зрения этот процесс распадается на две части, получивших названия идентификации и семантической (или атрибутной) индукции. Первая часть определяет значения атрибутов для вхождений лексем, а вторая— по- нятий. 8.1.1. Атрибуты абстрактной программы Исходя из КС-грамматики и определяемого ею дерева разбора для данной програм- мы, мы можем судить в основном об иерархических отношениях между вхождения- ми понятий, а большая часть их свойств, гарантирующих семантическое соответст-
Глава 8. Контекстный анализ 585 вие вхождений понятий во входную и выходную строки, — то соответствие, дости- жение которого есть задача трансляции, может быть обнаружена только на основа- нии учета контекста данного вхождения. Необходимость учета контекста для построения выходной строки может быть про- демонстрирована хотя бы на таком простом примере обработки фрагмента исходного текста X := У;". На основании КС-грамматики будет обнаружено, что это оператор присваивания, левая и правая части которого состоят из идентификаторов. Такая ин- формация, однако, не дает однозначных ответов на следующие вопросы. Можно ли реализовать этот оператор приданием переменной X значения, совпадающего с теку- щим значением переменной Y, или для получения нужного значения А'требуется его вычисление в соответствии с описанием процедуры без параметров У? Совпадают ли типы переменных X и Y или значение переменной Y должно быть предварительно преобразовано к типу переменной X? Перечень возможных альтернатив можно про- должить, допустив, например, что X или Y является формальным параметром. Вхождению понятия или лексемы, выделенному в дереве разбора данной программы, может быть поставлена в соответствие совокупность атрибутов и их значений. При этом то, какие атрибуты имеют смысл для данного вхождения, зависит от того, что за конструкция языка овеществлена в нем, а каковы значения этих атрибутов в общем случае зависит не только от контекста вхождения, но и от выбранного (из допусти- мых для понятия способов) синтаксического строения данного вхождения (т. е. от вида поддерева дерева разбора, соответствующего данному вхождению). Например, для такого типа лексемы, как идентификатор, обычно определен атрибут "вид", значением которого могут быть признаки метки, простой переменной, про- цедуры и т. п. Если значение атрибута "вид" для вхождения идентификатора совпа- дает с признаком переменной, то для него определен атрибут "тип", значениями ко- торого могут являться признаки целого, вещественного, логического и т. п. Далее, для любого оператора может быть определен атрибут "помеченность" со значениями "снабжен меткой, на которую нет перехода", "снабжен меткой, на которую разрешен переход", "не снабжен меткой" и атрибут "переход" со значениями "заведомо не пре- рывает естественную последовательность выполнений операторов" и "может преры- вать естественную последовательность выполнений операторов". Для выражения обычно определены такие атрибуты, как "тип" (аналогично атрибуту "тип" для про- стой переменной) и "число промежуточных переменных для реализации выражения" со значениями, являющимися натуральными числами. Приведенные примеры показывают, что выбор совокупности атрибутов при трансля- ции основывается как на необходимости выразить явные свойства понятий языка, зафиксированных в его семантике, так и на введении специальных признаков, удоб- ных для трансляции понятия. Кроме того, иногда удобно синтаксические или семан- тические различия также выражать атрибутами. Например, обычно не выделяется такой тип лексем, как логическая константа, а используется общий тип константы, различие же между константами выражается значениями атрибутов. Некоторые из представленных примеров атрибутов указывают на то, что значения атрибутов для части вхождений понятий или лексем могут быть определены в про- цессе лексического или синтаксического анализа. Однако для большинства конст-
586 Часть II. Применение графов и граф-моделей рукций и атрибутов процесс построения атрибутного дерева выделяется как логиче- ски обособленный этап контекстного анализа. С логической точки зрения этот про- цесс распадается на две части, получившие названия идентификации и семантиче- ской (или атрибутной) индукции. Первая часть определяет значения атрибутов для вхождений лексем, а вторая — для понятий. 8.1.2. Области видимости и идентификация Правила языка для каждой программы и каждой лексемы задают однозначное раз- биение лексической свертки на непересекающиеся части (например, через модули в Фортране или блоки в Паскале), как правило, синтаксически выделяемые и называе- мые областями действия. Внутри одной и той же области действия все вхождения данной лексемы изображают один и тот же семантический объект, а в разных облас- тях действия — разные объекты. Области действия разбивают все вхождения данной лексемы на классы вхождений лексем, называемых семантическими лексемами. Под атрибутом семантической лексемы понимается атрибут, являющийся общим для всех вхождений лексем, образующих соответствующий класс. Среди всех вхождений семантической лексемы в программу для каждого атрибута может существовать не более одного вхождения, называемого определяющим (вхож- дения, не являющиеся определяющими, называются использующими). Как правило, одно и то же вхождение, определяющее для всех атрибутов семантической лексемы, и оно выделяется текстуально. Отсутствие определяющего вхождения у семантической лексемы предполагает неиз- менность значений всех ее атрибутов во время исполнения программы. Примерами таких семантических лексем являются классы всех вхождений в программу на языке Паскаль (стандартных) идентификаторов integer или input, а также классы вхожде- ний встроенных функций sin или cos в программу на Фортране. Если же семантическая лексема содержит определяющее вхождение, то правила свя- зывания предполагают, что в каждый момент обработки данного (определяющего) вхождения исполняющей машиной, определяющей семантику языка, осуществляется вычисление значений у всех определяемых им атрибутов семантической лексемы и эти значения сохраняются вплоть до следующей (по времени) обработки опреде- ляющего вхождения, а если ее не будет, то до конца выполнения программы. В языках с блочной структурой области действия образуются с помощью блоков, которые попарно либо не пересекаются в программе, либо один вложен в другой. Семантические лексемы в языках с модульной структурой определяются на основе правил видимости, задающих в явном виде объединение в одну семантическую лек- сему использующего и определяющего вхождения в два (непересекающихся) модуля. В простейшем случае правила видимости требуют для каждого модуля явного указа- ния списка лексем, определяющие вхождения которых имеются в данном модуле, но видны из других модулей. Другой способ — это указание для модуля списка других модулей, из которых видны определяющие вхождения данного, и списка модулей, определяющие вхождения которых видны из данного модуля. Наиболее простой подход к реализации идентификации, который возможен внутри одной области действия, состоит в том, что по всем определяющим вхождениям се-
Гпава 8. Контекстный анализ 587 мантических лексем строится так называемая таблица объектов, каждым элементом которой является совокупность, образованная из синтаксической лексемы, опреде- ляющей вход в таблицу, и значений ее атрибутов (самих значений или ссылок на них), задаваемых определяющим вхождением. Одновременно с заполнением таблицы проводится проверка на существование двух или более определяющих вхождений для одного имени — перед пополнением таблицы объектов элементом проверяется, не имеется ли уже в таблице элемент с данным именем. После построения таблицы идентификация завершается рассмотрением использующих вхождений. Атрибуты найденного по имени элемента переносятся на использующее вхождение; обычно это реализуется явной ссылкой в использующем вхождении на соответствующий эле- мент таблицы объектов. Когда одновременно требуется обрабатывать сразу несколько областей действия, нельзя отождествлять два текстуально совпадающих имени, если они находятся в разных областях действия. Поэтому в случае пересекающихся областей действия вход в таблицу объектов должен определяться по совокупности, состоящей из син- таксической лексемы и обозначения области действия. В большинстве случаев области действия задаются блочной структурой программы. Если это так, то можно обозначать области действия натуральными числами — но- мерами соответствующих блоков, которые получаются при нумерации блоков слева направо в порядке текстуального следования открывающих скобок блоков (или при левостороннем нисходящем обходе дерева разбора). При этом, идентификация осу- ществляется одновременно с нумерацией путем организации стека номеров блоков, который пополняется новым номером при встрече открывающей скобки блока и вы- талкивает верхний свой элемент при закрывающей скобке. Состояние стека дает в каждой точке программы номера охватывающих блоков. Для идентификации при определяющем вхождении вход в таблицу строится по лексеме и номеру блока, на- ходящемуся наверху стека, а при использующем вхождении осуществляется после- довательный поиск элемента в таблице по номерам блоков, хранящихся в стеке (при этом элементы стека перебираются подряд, начиная с верхнего). В случае модулей обозначением области может быть имя модуля. 8.1.3. Атрибутная индукция В отличие от идентификации, когда значения атрибутов обнаруживаются на основа- нии синтаксического строения определяющего вхождения, при атрибутной индукции атрибуты некоторого понятия вычисляются как функции значений атрибутов других вершин дерева разбора. Семантическое описание языка фиксирует, какие вершины следует использовать для вычисления значения атрибута данного понятия и каков вид функциональной зависимости. Задача атрибутной индукции состоит в заверше- нии построения атрибутного дерева распространением атрибутной информации по дереву разбора (предполагается, что идентификация предшествует атрибутной ин- дукции). Одним из простейших видов функциональной зависимости атрибутов является функциональная зависимость для такого атрибута выражения, как тип. При вычисле- нии его значений используются значения этого атрибута только непосредственных
588 Часть II. Применение графов и граф-моделей составляющих этого выражения и семантически заданные правила приведения. Так, для выражения (a + b) (с - d), где а и b — вещественные, а с и d целые, поддеревья атрибутного дерева после иден- тификации и после атрибутной индукции будут иметь вид, приведенный на рис. 8.1. Понятия обозначаются просто знаками операций, а значения атрибутов г — для при- знака вещественного и I — для признака целого. Рис. 8.1. Пример атрибутной индукции: а — после идентификации, б — после атрибутной индукции Нетрудно заметить, что в этом примере вычисление атрибутов шло "снизу вверх" последовательно от висячих вершин к корню, а значение атрибута "тип" для состав- ного выражения бралось просто из значений атрибутов компонент с учетом доми- нантности признака вещественного. Как видно из этого же примера, атрибутная индукция служит источником выявления действий по приведению, которые могут быть не указаны явно в программе, что мо- жет послужить причиной появления новых вершин в атрибутном дереве. Так, в при- веденном примере если мы хотим сделать все действия явными, то должны ввести операцию преобразования целого в вещественное целвещ, и соответствующее атри- бутное дерево представлено на рис. 8.2. Рис. 8.2. Появление новых вершин в атрибутированном дереве
Глава 8. Контекстный анализ 589 Правила вычисления атрибутов при атрибутной индукции могут одновременно с вы- явлением возможных приведений также фиксировать невозможность приведения, что даст информацию о семантической ошибке. В общем случае значения данного атрибута в данной вершине могут определяться и значениями других атрибутов (других вершин или той же самой). Рассмотрим пример, который заключается в определении числа нужных регистров для генерации арифметического выражения, если команды машины таковы, что ле- вый операнд арифметического выражения должен находиться в регистре. Ограни- чимся только такими выражениями, которые строятся из идентификаторов простых переменных с помощью бинарных арифметических операций и скобок. Введем два атрибута число регистров и (значения— неотрицательные числа) и признак лево- го операнда / (значения — истина и ложь). Значения первого атрибута вычисляются для промежуточных вершин по значениям атрибутов компонент, а именно: п(Е) = если (л(Е|) = п(Е2)) то п(Е}) + 1 иначе гпах(л(£|), «(£2)), где £| и Е2 — соответственно левая и правая составляющие, образующие выражение Е применением к ним арифметической операции, и и(£) = л(£0), если выражение £ образуется взятием в скобки Ео. Для простой переменной (висячей вершины) и(г/) = если 1(a) то 1 иначе О, т. е. зависит от значения атрибута / для той же вершины, который определяется соот- ношениями /(£,) = истина; /(£?) = ложь; /(£0) = /(£), а для корня (для всего выражения целиком) значение / равно истина. Итак, в общем случае значение атрибута для данного понятии определяется по зна- чениям каких-либо атрибутов его компонент и тех понятий, компонентой которых оно является. Вид зависимости определяется как самим понятием, так и правилом его конструирования. Атрибутная индукция осуществляется некоторым обходом (или совокупностью обходов) дерева разбора и составляющих его поддеревьев. Так, в рас- смотренном примере определения числа нужных регистров для генерации арифмети- ческого выражения вычисление атрибутов достигается сначала нисходящим, а затем восходящим обходами дерева выражения. Для эффективности атрибутной индукции порядок обхода (или обходов) выбирается с учетом всех функциональных зависимо- стей для атрибутов с тем, чтобы при каждом обходе вычислялось максимально воз- можное число атрибутов. Как уже отмечалось, при атрибутной индукции может осуществляться некоторое преобразование исходного дерева, приводящее, в частности, к появлению новых вершин. Так как семантика языка может задавать не только зависимости атрибутов, но и ограничения на множество допустимых значений атрибутов в зависимости от правила конструирования понятия или правила согласования значении атрибутов, то атрибутная индукция обнаруживает семантические ошибки, связанные с нарушением ограничений или правил согласования.
590 Часть II. Применение графов и граф-моделей 8.2. Атрибутные грамматики Среди всех формальных методов описания языков программирования атрибутные грамматики получили, по-видимому, наибольшую известность и распространение. Причиной этого является то, что формализм атрибутных грамматик основывается на дереве разбора программы в КС-грамматике, что сближает его с хорошо разработан- ной теорией и практикой построения трансляторов. 8.2.1. Определение атрибутных грамматик Пусть G— некоторая КС-грамматика, состоящая из алфавита нетерминалов N, алфа- вита терминалов Т, множества правил вывода Р и начального символа Е. Правила выводар G Р будем записывать в виде Р : Хо —> Х\Х2 —Хп{ру и предполагать, что G является редуцированной КС-грамматикой, т. е. в ней нет не- терминалов, не принадлежащих ни одному из выводов цепочек из L(G) — языка, по- рожденного грамматикой G. Атрибутная грамматика состоит из КС-грамматики G, называемой ее основой (или базой), отображений S и 1, ставящих в соответствие каждому символу Xe(V\jW) непересекающиеся конечные множества S(X) и 1(Х) его синтезируемых (или синте- зированных) и наследуемых (или наследованных) атрибутов, а также из множеств М(р) так называемых семантических правил (правил вычисления значений атрибу- тов) для каждого правила р е Р. Запись а(Х) означает а е А(Х), где А(Х) = 1(Х) О S(X) — множество атрибутов, постав- ленных в соответствие символу X, а / и S'— множества всех наследуемых и синтези- рованных атрибутов соответственно. Пусть р : АЬ —> А) Х2 ... Хпц,)— некоторое правило грамматики G. Говорят, что имеется вхождение атрибута а при j-м символе Xt правила р (обозначается a(j)), если а е Л(Л}). Для a(j) иногда используются также обозначения Xj.a и а*. Множество М(р) состоит из семантических правил, определяющих вычисление элементов из S' (%0) и 1 (Х}) для j G[l, п{р}} в терминах элементов А(Х}, 0 < i < п{р), и имеющих вид яо0о) = Лд,(,)(я101X ’ ak{h». где либо «о = 0 и а0 е S(X0), либо 1 < i0 < п{р) и а0 е /(А',() Если М(р) содержит семантическое правило, определяющее вычисление а0{10) по ai(ji),..., ak{i£), то говорят, что a0{ia) локально зависит от a\(i\), ..., ak{ik). В частном случае к может быть равно нулю, и тогда говорят, что атрибут a0{i^) получает в каче- стве значения константу. Пусть W(p) обозначает множество вхождений атрибутов в правило р, т. е. W(р) = {a{i): а е А(Х,), 0 < I < п(р')}.
Гпава 8. Контекстный анализ 591 Таким образом, семантические правила из М(р) индуцируют на W(p) отношение ло- кальной зависимости D(p), такое что b(j) D(p) a{i) тогда и только тогда, когда b(j) появляется в определении а{1). Граф локальной зависимости в продукции р — это граф отношения D(p) на множест- ве W(p). Будем считать, что значения атрибутов терминальных символов— константы, т. е. их значения не зависят от других атрибутов. Атрибутная грамматика является грамматикой в нормальной форме (или нормализо- ванной), если ее семантические правила определяют вычисления атрибутов из И'(р) по атрибутам из ЦХ0) и S(Xt) для 1 <j < п{р), т. е. они используют только атрибуты, определенные вне продукции р. Всякая атрибутная грамматика может быть преобразована в нормальную форму по- средством простого преобразования семантических определений, если D(p) является ациклическим. Дерево вывода в КС-грамматике G, вершины которого помечены соответствующими атрибутами, называется атрибутным (или атрибутированным) деревом грамматики с основой G. Атрибутное дерево называется заполненным, если каждому его атрибу- ту присвоено некоторое конкретное значение Правила вычисления атрибутов опре- деляют, как и по значениям каких атрибутов данной вершины и атрибутов ее соседей в дереве (отца, сыновей и братьев) можно вычислить тот или иной ее атрибут. При этом для любой вершины дерева значения ее синтезируемых атрибутов вычисляются без использования атрибутов ее отца и братьев, а значения наследуемых — без ис- пользования атрибутов ее сыновей. Таким образом, значениями синтезируемых ат- рибутов информация передается по дереву снизу вверх, что позволяет синтезировать внутренний контекст для корня любого поддерева. Наследуемые атрибуты переносят информацию по дереву сверху вниз и позволяют определять внешний контекст корня любого поддерева. Пусть /— дерево вывода в G. Граф составной зависимости R/t) получается объеди- нением графов D(p), соответствующих каждой продукции, принадлежащей дереву. Если рассмотреть дерево t с корнем Хо, отношение R //) индуцирует на /!(А0) отно- шение синтезируемых зависимостей для дерева, растущего из Хо, которое обознача- ется sd,(X0). Это отношение является частичным порядком, и его дуги идут из 1(Х0) к 8(Х0), если атрибутная грамматика находится в нормальной форме. Для вершины q дерева t через sort(q) и label(q) обозначаются соответственно нетер- минал корня поддерева, растущего из q, и продукция р, примененная к корню этого поддерева. Пусть р = label(q), где Р-х0^х1х2 ...хп{„}, тогда Хо занимает в поддереве с корнем q позицию корня q (обозначается Хч), a Xf, где 1 < z < п{р), — позицию его /-го сына q, (обозначается Xq ).
592 Часть II. Применение графов и граф-моделей Если рассмотреть вершину q дерева I, у которой sort(<y) = X, и удалить целиком под- дерево, исходящее из q, за исключением самой вершины q, отношение R /г) индуци- рует на А(Х) отношение наследуемых зависимостей для контекста Хч, обозначаемое ад;)- Для некоторого заданного правилар, примененного к вершине q дерева /, отношение id, (Xq )usd, (X4i )e>sd, (Xq^ )uDq (p) обозначает тот порядок по зависимостям, который должен сохраняться во время вы- числения атрибутов Wq(p), где Dq(p) и ^(р) обозначают вхождения £>(р) и lV(p) в вершине q для правила р. Заметим, что для данного дерева t отношения sd могут быть вычислены за один об- ход снизу вверх дерева t, а для вычисления отношений id за один обход сверху вниз дерева t требуется предварительное нахождение sd. Вход-выход отношение, обозначаемое Ю(Х) (и соответственно выход-вход отноше- ние, обозначаемое О1(Х)), определяется как объединение всех отношений sd{X) (соот- ветственно id(X)) на любом дереве, растущем из Д'(для любого контекста А), т. е. IO(X)=\Jtsd'(X) для всех деревьев t с корнем X, OI(X)=\Jtid'(X) для всех деревьев t, содержащих поддерево с корнемX. Через Ж[0 обозначается множество всех вхождений атрибутов a(q) в дерево t. И7(1) может рассматриваться как множество переменных, которые в процессе вычисления должны получить значения. Атрибутная грамматика называется ациклической (или корректной), если ацикличе- ским является граф зависимостей атрибутов любого его дерева вывода. Очевидно, что для любого дерева t существует порядок вычисления атрибутов тогда и только тогда, когда грамматика является ациклической. 8.2.2. Пример атрибутной грамматики Перевод любой двоичной записи вещественного числа в значение этого числа (на- пример, цепочки 1101.01 в число 13.25) может быть определен с помощью следую- щей атрибутной грамматики. Пусть основа G состоит из множества нетерминалов {Z, BIN, BIT}, множества терми- налов {0, 1,.} и множества продукций Pi -Z-t BIN.BIN р2 : BIN -> BIN BIT p3-.BIN-*e pe BIT 1 ps-.BIT^D
Гпава 8. Контекстный анализ 593 Множество А = {г, I, v} содержит как синтезируемые S = {/, v}, так и наследуемые 1= {г} атрибуты: X.v— вещественное число, представленное цепочкой, выведенной из Л, Х.1 — длина цепочки, выведенной из Л, Х.г — ранг самого правого бита строки, выведенной из X, Ж2)=М, A{BIN) = {г, I, v}, А(В1Т)= {г, v}. Продукциям ставятся в соответствие следующие семантические правила: рх .7.^ BIN.BIN Z.v = BINt.v + BIN2.v BINf.r = 0 BINt r = -BIN2 .1 p2 : BIN BIT BIN0 = BIN\.v + BIT.v BIN0 = BINI + 1 BIT.r = BIN0 r BINi .r = BIN0 r + 1 P2:BIN->e BIN.v = 0 BIN I = 0 P4 . BIT BIT.v = 2mr P5:BIT—>0 BIT.v = 0 Рис. 8.3. Графы локальной зависимости Для этой атрибутной грамматики графы локальной зависимости изображены на рис. 8.3. На рис. 8.4 приведен граф составной зависимости цепочки 10.01. Отношения 1О(Х), О1(Х) для А' ё {Z, BIN, BIT} даны на рис. 8.5. 8.2.3. Атрибутное вычисление Эффективность использования атрибутных грамматик во многом зависит от способа решения задачи вычисления атрибутов (или нахождения значений неизвестных атри- бутов W(/) для каждого дерева /).
594 Часть II. Применение графов и граф-моделей Рис. 8.4. Граф составной зависимости для цепочки 10.01 Рис. 8.5. Вход-аыход и выход-вход отношения Первый шаг, который нужно при этом сделать, состоит в определении порядка {пла- на или стратегии) вычисления, — такого линейного порядка T{t) на неизвестных W{t), который не противоречит R(t), т. е. R(t) g T{t). В случае, когда грамматика корректна, указанная задача для заданного t является задачей топологической сортировки, допускающей эффективное решение. Алгоритм заполнения атрибутных деревьев может предполагать, что выбор страте- гии заполнения и собственно вычисление по этой стратегии осуществляются динами- чески, во время работы транслятора, построенного с помощью атрибутной граммати- ки. Конструктор динамического алгоритма транслирует семантические функции н
Гпава 8. Контекстный анализ 595 либо проверяет корректность исходной атрибутной грамматики, либо не содержит проверки из-за большой ее трудоемкости (и тогда ошибка в грамматике может быть обнаружена только при работе транслятора). Алгоритм вычисления атрибутов может включать статический (т. е. до работы транслятора) этап выбора стратегии заполнения дерева, что может существенно по- высить эффективность транслятора, построенного по атрибутной грамматике, но по- требовать сужения класса атрибутных грамматик до некоторого подкласса коррект- ных. Конструктор статического алгоритма осуществляет трансляцию семантических функций и проверку принадлежности атрибутной грамматики допустимому подклас- су корректных атрибутных грамматик; если это необходимо, он также включает вы- бор стратегии заполнения атрибутных деревьев. Алгоритмы заполнения могут быть как детерминированными, так и недетерминиро- ванными, предполагающими произвольный порядок вычисления значений активных (т. е тех, которые могут быть вычислены в данный момент) вхождений атрибутов в атрибутное дерево. Условия задержки (соответственно активации) вхождения атри- бута определяются отсутствием (соответственно наличием) значений аргументов семантического правила, вычисляющего значение данного вхождения атрибута. Та- ким образом, если граф зависимостей атрибутов дерева ациклический, то, начиная с присваивания константного значения некоторому атрибуту, не имеющему заходя- щих дуг в графе зависимостей, может происходить заполнение всего атрибутного дерева в порядке, зависящем от предыдущих вычислений. Детерминированные алгоритмы, в которых порядок заполнения атрибутного дерева фиксируется до начала вычисления атрибутов, разделяются на алгоритмы с жесткой стратегией, в которых порядок заполнения один и тот же для всех атрибутных де- ревьев, и алгоритмы с гибкой стратегией, в которых порядок заполнения определя- ется для конкретного атрибутного дерева. После того как план вычисления T(t) найден, возможны два варианта его использова- ния. вычислять, начиная с минимальных или максимальных элементов в отношении. Пусть M7jn(z)— минимальные, a PKout(z)— максимальные элементы. Вычислители, которые начинают с присваивания значений атрибутам И7,//), называются восходя- щими (снизу вверх или управляемыми данными) вычислителями. Вычислители, кото- рые вначале рассматривают атрибуты И7,,,,)/) (или, по крайней мере, некоторое их подмножество), называются нисходящими (сверху вниз или управляемые запросами) вычислителями. Важное преимущество нисходящих вычислителей связано с тем, что они позволяют вычислять любое заданное подмножество И^^г) множества H7out(z), которое обычно образуется из всех синтезированных атрибутов начального символа. При таком под- ходе возможно различать среди переменных подмножество полезных атрибутов (обозначается Usefulp(/)), т. е. тех, которые реально вовлечены в вычисление И^еХ/), а также подмножество тупиков (обозначается Dead-endsД/)), т. е. тех атрибутов из W(t), которые не являются полезными. Вычислитель оптимален по времени, если он вычисляет, причем по одному разу, только элементы из Useful^ (t), где RJ(t)— отношение частичного порядка, полу-
596 Часть II. Применение графов и граф-моделей ценное по локальным зависимостям. В качестве других критериев эффективности вычислителя иногда используются следующие: вычисляет ли он без повторения IV(f) или Useful/^/) для отношения R, содержащего /?,/, или является ли время его работы линейным по отношению к W(l) или к Useful/((/) при условии снятия ограничения на число вычислений одного атрибута. Критерию оптимальности могут удовлетворять лишь нисходящие вычислители, ис- пользующие отношение R^t), но на практике по причинам, связанным с экспоненци- альной природой проверки ацикличности грамматики, нет особых преимуществ у нисходящей стратегии по отношению к восходящей. Не очень существенное ее пре- имущество связано с тем фактом, что нисходящий вычислитель может выполнять динамические оптимизации путем, например, ликвидации вычислений атрибутов в неиспользуемых ветвях условных операторов. Их называют семантическими тупи- ками в отличие от статических тупиков, которые входят в Dead-endsft(z); последние определяются потоком управления семантических правил. Для атрибутной грамматики, рассмотренной в разд. 8.2.2, атрибуты любого нетерми- нала могут вычисляться в одном и том же порядке для любого дерева (см. рис. 8.5). Например, в правиле р2 указанный порядок может удовлетворять любому контексту, в котором данное правило может быть применено. На рис. 8.6 изображены зависимо- сти атрибутов в этом правиле: сплошные стрелки изображают D(p), а штриховые — зависимости Т(Х), индуцированные контекстом. Рис. 8.6. Зависимости атрибутов во втором правиле Общий порядок вычислений является следующим: BIN,.l, BIN0.l, BlNo.r, BlT.v, ВП\.г, BIT,.r. BIN,г, BIN,.v, B/Nu.v, если необходимо вычислять все атрибуты любого дерева. Заметить, что для строки 10.01, рассмотренной в качестве примера, значение BIN.I в левом поддереве не требу- ется для вычисления Zv, единственного нужного значения. Помимо этого имеется также много других тупиков. Для оценки практической эффективности вычислителя используются следующие критерии (в предположении, что каждое семантическое действие выполняется за единицу времени, а атрибутная грамматика является нормализованной): □ отличие от UsefulK (r) (число вызовов семантических функций), т. е. число вы- численных атрибутных вхождений; □ время построения плана;
Гпава 8. Контекстный анализ 597 П время оптимизации размера плана; □ эффективное глобальное время и объем памяти процесса вычисления атрибутов. 8.3. Конструирование абстрактных синтаксических представлений Под абстрактным синтаксическим представлением программы понимается такое ее представление, которое содержит информацию о синтаксической структуре про- граммы в виде, удобном для ее последующей обработки. 8.3.1. Абстрактное синтаксическое дере во и построение дерева выражения Абстрактное синтаксическое дерево является конденсированной формой дерева раз- бора, удобной для представления структуры языковых конструкций с точки зрения семантики. Например, продукция £ —> если В то S'] иначе S2 может войти в абстрактное синтаксическое дерево в виде, изображенном на рис. 8.7. если-то-иначе Рис. 8.7. Фрагмент абстрактного синтаксического дерева В абстрактном синтаксическом дереве операции и ключевые слова не встречаются в качестве листьев, а ассоциируются с внутренними вершинами, которые могут выступать отцами этих листьев. Например, для дерева разбора выражения 3-5+4, изображенного на рис. 8.8, а, абстрактное синтаксическое дерево, называемое дере- вом выражения, имеет вид, представленный на рис. 8.8, б. Конструирование дерева выражения аналогично трансляции выражения в так назы- ваемую польскую обратную запись, получаемую из дерева выражения выписыванием пометок вершин в процессе постфиксного его обхода. Строятся поддеревья для под- выражений путем создания некоторой вершины для каждой операции и каждого опе- ранда. При этом сыновьями у некоторой вершины, представляющей операцию, ста- новятся корни поддеревьев, представляющих подвыражения, которые являются опе- рандами этой операции.
598 Часть II. Применение графов и граф-моделей Рис. 8.8. Для выражения 3-5 + 4. а — дерево разбора, б — абстрактное синтаксическое дерево Каждая вершина в дереве выражения может быть реализована записью, состоящей из нескольких полей. Для вершины операции (помеченной символом операции) одно поле содержит имя операции, а остальные— ссылки на вершины, представляющие операнды. При этом в процессе трансляции вершина может иметь дополнительные поля для хранения значений (или ссылок на значения) атрибутов, поставленных в соответствие этой вершине. Предположим, что имеются следующие функции: □ сдверш(опер, лев, прав) создает вершину операции с пометкой опер и двумя поля- ми, содержащими ссылки лев и прав, и выдает ссылку на эту вершину; П сдлист(1щен, вход) создает идентификаторную вершину с пометкой идеи и по- лем, содержащим значение вход, являющееся указателем на вход в таблицу объ- ектов, и выдает ссылку на эту вершину; □ сдлист(чнсло, знач) создает численную вершину с пометкой число и полем, со- держащим значение знач, являющееся значением целого числа, и выдает ссылку на эту вершину. Например, следующая последовательность вызовов функций р, := сдлист^идеп, входа); р2 := сдлист(число, 4); р3 := cdeepuif', р}, р2); р$ := сдлис«?(нден, входЬ); р5 ;= := сдверш('+', р3, р.-,) осуществляет построение дерева выражения для а — 4 • Ь, изо- браженное на рис. 8.9, а. В ней ...,р3 являются указателями на вершины, а входа и входЬ— указателями на входы в таблицу объектов для а и Ь соответственно. Дерево конструируется снизу вверх. Вызовы функций сдлист(нд.еп, входа) и сдлист(чпсло, 4) создают листья для а и 4; ссылки на эти вершины сохраняются в р\ и р2. Затем вызов сдверш^-', р}, р2) конструирует внутреннюю вершину с листьями для а и 4 в качестве сыновей. Через два последующих шага р3 получает ссылку на корень построенного дерева. В табл. 8.1 приводится описание атрибутной грамматики, определяющее построение дерева выражений для арифметических выражений, содержащих операции '+' и
Глава 8. Контекстный анализ 599 Она использует в качестве основы стандартную КС-грамматику, правила которой планируют вызовы функций сдверш и сдлист для конструирования дерева. Синтези- руемый атрибут указ для Е иТ сохраняет ссылки, возвращаемые вызовами функций, и обозначается через Е.указ и Т.указ соответственно. Таблица 8.1. Атрибутная грамматика Продукция Семантическое правило + Т Е. указ := сдверш^+', Е\ .указ. Т. указ) Е-^Ех-Т Е. указ := сдверш^-, Е\.указ. Т. указ) Е-* Т Е. указ := Т. указ Т^(Е) Т. указ := Е. указ Т —> идеи Т. указ := сдлист (идеи, идеи, вход) Т—> число Т. указ := сдлист(чнсло, число, знач) для а б) Рис. 8.9. Представления выражения а - 4 • Ь: а — дерево выражения, б — атрибутированное дерево разбора а) На рис. 8.9, б приведено атрибутированное дерево разбора для a - 4 * b вместе (изо- бражено штриховыми линиями) с построенным деревом выражения. Вершины дере- ва разбора, помеченные символами Е и Т, используют синтезируемый атрибут указ
600 Часть II. Применение графов и граф-моделей для хранения ссылок на вершины дерева выражений, представляющие соответст- вующие нетерминалы. Семантические правила, ассоциированные с продукциями Т—> идеи и Т—> число оп- ределяют атрибут Т.указ, ссылающийся на новый лист для идентификатора и числа соответственно. Атрибуты иден.вход и число.знач являются строковыми, заполняе- мыми лексическим анализатором. 8.3.2. Дэги выражений Дэг выражения идентифицирует общие подвыражения в выражении. Подобно дереву выражения дэг имеет некоторую вершину для каждого подвыражения выражения, причем внутренняя вершина изображает операцию, а ее сыновья — операнды опера- ции. Различие состоит в том, что вершина в дереве, изображающая общее подвыра- жение, имеет более одного отца; в дереве выражения это общее подвыражение мож- но представить за счет дублирования поддеревьев. На рис. 8.10 изображен дэг выражения а +а (Л - с) + (/? с) • d. Лист а имеет двух отцов, поскольку он является общим подвыражением для а и а * (Ь - с). Оба вхожде- ния общего подвыражения Ь — с тоже представлены одной вершиной, которая также имеет двух отцов. Рис. 8.10. Дэг выражения а + a (Ь - с) + (Ь - с) d Атрибутная грамматика, приведенная в табл. 8.1, будет конструировать дэг, а не де- рево, если модифицировать операции для конструирования вершин. При обработке выражения с общими подвыражениями будет получаться дэг. если новая функция конструирования вершин перед созданием вершины всегда будет проверять, нет ли указанной вершины среди построенных. Например, до построения новой вершины с пометкой операция и полями, содержащими ссылки лев и прав, вызов сдверш(операция, лев, прав) может проверить, не построена ли уже такая вершина. Если построена, то вызов сдверифоперация, лев, прав) может возвратить ссылку на ранее построенную вершину. Подобным образом нужно модифицировать функцию сдлист.
Гпава 8. Контекстный анализ 601 8.3.3. Метод нумерации для конструирования вершин в дэге Во многих приложениях вершины представляются записями, сохраняемыми в масси- ве, как это показано на рис. 8 11. Здесь каждая запись имеет поле метки, которое оп- ределяет природу вершины, причем ссылка на вершину осуществляется через ее ин- декс или позицию в указанном массиве Целочисленный индекс вершины по тради- ции часто называют номером значения. Например, используя номера значений, можно сказать, что вершина 3 имеет метку "+", ее левый сын — это вершина 1, пра- вый сын — вершина 2 Следующий алгоритм можно использовать для представления выражения в виде дэга. Алгоритм 8.1 Данные и операции. Предполагается, что вершины хранятся в массиве в виде, изображенном на рис. 8.II, и что каждая вершина представляется номером своего значения. Пусть сигнатурой некоторой вершины операции будет называться тройка {op, I. г), состоящая из ее метки ор, левого сына I и правого сына г Дано. Метка ор, вершина / и вершина г. Требуется. Выдать вершину с сигнатурой {op, /. г). Дэг Рис 8.11. Представление вершин в виде массива записей Метод. Просмотреть массив для поиска вершины m с меткой ор, левым сыном I и правым сыном г. Если существует такая вершина, выдать пт, иначе создать новую вершину п с меткой ор, левым сыном / и правым г и выдать п. Очевидный способ определения, есть ли уже в массиве вершина т, состоит в хране- нии всех ранее созданных вершин в виде списка и в проверке каждой вершины в спи-
602 Часть II. Применение графов и граф-моделей ске на предмет наличия у нее желаемой сигнатуры. Поиск для m можно осуществить более эффективным способом, если использовать к списков, называемых блоками, и применять функцию расстановки h для определения, какой блок должен просматри- ваться. Функция расстановки h вычисляет номер блока по трем значениям op, I и г. Она бу- дет всегда возвращать один и тот же номер блока, если заданы одни и те же аргумен- ты. Если m не находится в блоке h(pp, I, г), тогда создается новая вершина п и добав- ляется к этому блоку, так что последующий поиск вершины с той же сигнатурой бу- дет находить ее в данном блоке. Функция расстановки может размещать вершины с разными сигнатурами в один и тот же блок, но на практике при подходящем выборе функции расстановки можно ожидать, что каждый блок будет содержать небольшое число вершин. Каждый блок можно реализовывать в виде связанного списка, как это показано на рис. 8.12. Каждый элемент в связанном списке представляет вершину. Головы бло- ков, состоящие из указателей на первые элементы в списке, запоминаются в массиве. Номер блока, возвращаемый Ырр, I, г), является индексом в этом массиве голов блоков. Массив голов блоков, индексированный значением ключей Рис. 8.12. Представление блоков Рассмотренный алгоритм может быть адаптирован для его применения и к вершинам, которые в памяти не размещены последовательно. Во многих компиляторах вершины размещаются так, чтобы ликвидировать перераз- мещение массива, который в большинстве случаев может хранить достаточно много вершин и лишь иногда не может разместить все нужные вершины. В этом случае не предполагается, что вершины занимают последовательный участок памяти, и исполь- зуются указатели для ссылок на вершины. Если удается построить функцию расста- новки, которая вычисляет номер блока по метке и указателям на сыновей, то можно применять указатели на вершины вместо номеров их значений. Иначе, можно прону- меровать вершины любым способом и использовать полученные номера в качестве номеров значений вершин.
Глава 8. Контекстный анализ 603 8.4. Основные подклассы атрибутных грамматик и вычислений Рассматривая те или иные подклассы атрибутных грамматик, можно достигать более эффективного использования этого формализма. 8.4.1. Чисто синтезированные грамматики Атрибутная грамматика называется чисто синтезируемой (или S-грамматикой), если I— 0, и чисто наследуемой (или 1-грамматикой), если 5 = 0. Определения 5- и /-грамматик имеют симметричный вид, однако только 5-грам- матики играют важную роль как с теоретической, так и с практической точки зрения. Фактически 5-грамматики по мощности не уступают машинам Тьюринга и не требу- ют динамических построений, поскольку определенный порядок вычисления присущ любой 5-грамматике. Реально может быть построена некоторая оптимальная по вре- мени система, которая объединяет синтаксический и семантический анализы, напри- мер предоптимальный восходящий вычислитель, линейный по lT(t), или оптималь- ный нисходящий вычислитель, который может комбинироваться с методом разбора различных стратегий. Непосредственно видно, что такой вычислитель может быть соптимизирован по памяти и времени. Нужно заметить, что в 5-грамматике каждый атрибут можно рассматривать как ре- курсивную функцию, определенную над деревом t (они являются примитивно рекур- сивными схемами). Следовательно, легко построить по 5-грамматике нисходящий вычислитель, определенный рекурсивными функциями с деревом t в качестве един- ственного их аргумента, которые в качестве результата выдают значения атрибута (атрибутов) корня дерева. Различают статический и динамический размер вычислителя. Под статическим раз- мером понимается размер вычислителя как программы, т. е. размер кода и данных сконструированной программы вычислителя. Под динамическим размером понима- ется размер информации, добавленной к дереву t и множеству переменных W(t). По- нятно, что весь размер вычислителя равен сумме его статического и динамического размеров. Рекурсивный вычислитель 5-атрибутной грамматики имеет статический размер, про- порциональный размеру грамматики, и динамический размер, пропорциональный сумме размеров дерева t и стека рекурсивных вызовов, чья глубина совпадает с высо- той дерева t. Нет необходимости хранить W(t), но в таком случае вычисление может иметь экспоненциальную сложность, как показывает следующий пример. Дерево t рассматривается как скобочное выражение (рис. 8.13), для которого рекур- сивные функции имеют следующий вид: знач s(px(1))=/(знач S| (/), знач Sz (/)) знач Si (р2 (/))=f ( знач Si (t), знач Sz (t))
604 Часть II. Применение графов и граф-моделей знач s2 (p2(t})=f2 (знач (Z), знач (Z)) зиач51(рз)=а, знач Si(p3)=a2 Рис. 8.13. Графы локальных зависимостей Если результат не сохраняется, временная сложность вычисления значь{1) является экспоненциальной от высоты дерева (0(4"), если и является этой высотой, 0(2'"), если /и=| Ж(/)|), чт0 весьма отличается от времени оптимального вычислителя. Напротив, если промежуточные результаты сохраняются или если функции органи- зованы для вычисления всех синтезируемых атрибутов за один вызов, получается временная оптимальность в случае, когда все атрибуты являются полезными. Например, с вычислителем знач s(pi(t)) = f (знач (Z)), знач (р2 (t))=g( знач (Z)) , 3Ha4SiSi(p3(t)) = {al,a2), где знач s- s является функцией, определенной на паре значений следующим образом: g((x, у}) = (х, у), f2 (х, у)},
Гпава 8. Контекстный анализ 605 вычислитель становится оптимальным по времени, а динамический размер ограничен суммой размеров дерева / и стека исполнения. В качестве критериев емкостной эффективности вычислителя рассматриваются- □ статический размер (размер кода и данных); □ динамический размер (размер обрабатываемых данных в терминах t и W(t)). С точки зрения полноты рассмотрения при оценке эффективности вычислителя сле- довало бы принимать во внимание сложность его конструирования. Вместе с тем нетрудно проверить, что на конструирование вычислителя требуется столько же вре- мени, сколько необходимо на проверку принадлежности грамматики некоторому классу, и требуется столько же памяти, каков статический размер вычислителя или емкостная сложность проверки принадлежности грамматики. 8.4.2. /-упорядоченные грамматики Атрибутная грамматика называется l-упорядоченной, если существует семейство ли- нейных порядков { 7'(А)} для X e/V такое, что для любого р е Р, где Р ~~ %т(/>)’ является ациклическим Т(р) = Т(Х0) и Т(Х}) о... о Г(*„(„}) м D(p) Если грамматика /-упорядоченная, то для каждого дерева t порядок 7)7), полученный объединением порядков Т(р), является порядком вычисления. Можно запрограммировать вычислитель в виде последовательности, включающей вызовы для посещения поддеревьев вершин в правых частях и вызовы для просмотра контекста. Такие последовательности называются визитными последовательностя- ми и ассоциируются с каждой продукцией. Визитная последовательность, ассоциированная с правилом р2 из примера (см. разд. 8.4.1), по существу совпадает с той, которая описана в исходном примере, но расширена следующими вызовами процедур (для визитов к сыновьям и отцу): П визит!), Д') — вызов для выполнения z-го визита поддерева с корнем X; П финиш!), Д') — вызов для перехода на просмотр контекста; П вычисление(а, X) — вызов для вычисления X а. Последовательность BIN).!, BIN0.l, BIN0.r, BIT.v, ВП).г, ВП\.г, В IN), г, BIN).v, BINq.v редуцируется к двум этапам визитов и вычислений визит(\, BIN0); визит!), BIN)); вычисление!), BIN)); финиш(\, BIN)); визит(2, BIN0); вычисление^, BIT)', визит!), BIT); вычисление!?, BIN)); визит(2, BIN)); вычисле- ние^, BIN0); финиш(2, BIN0). Данная визитная последовательность не описывает вычислений, выполняемых вне правила р2, но сразу же после завершения визита (например, когда завершится ви- зит(2, BINi)) все значения, необходимые для непосредственно следующего вычисле- ния (здесь вычисление!?, BIN))), являются известными.
606 Часть II. Применение графов и граф-моделей Ясно, что можно построить эффективный вычислитель для такого вида грамматики: конечный автомат, ориентированный на визитные последовательности, и стек для рекурсивных вызовов визитов (чья глубина не превышает высоты дерева /)— подхо- дящие инструменты для вычисления переменных lV(t). Вычислитель восходящий (неоптимальный по времени, но линейный по размеру W(f) и без повторных вычислений), и он не теряет времени на разработку плана. Его ста- тический размер, очевидно, зависит линейно от размера грамматики (размера визит- ной последовательности); а его динамический размер определяется тем, что вычис- литель использует t, все переменные в И^г), которые хранятся в дереве I, и стек. Конструирование вычислителя должно включать выполнение теста членства. Опре- деление /-упорядоченности показывает, что оно несложно для проверки посредством транзитивного замыкания Т(р) в каждой продукции, если известно семейство {Т(Х)}. Однако исходным здесь является нахождение такого семейства, т. е. такого разбие- ния Я(Л), что все атрибуты в одной и той же подчасти Л(Л) могут быть вычислены во время одного и того же визита в любом дереве t. Указанная проблема УР-полная. Справедливо следующее свойство. А. Любая ациклическая грамматика может быть преобразована в эквивалентную l-упорядоченную грамматику, причем с теми же семантическими определениями, но имеющую экспоненциальный размер. 8.4.3. Сильно ациклические грамматики Атрибутная грамматика называется сильно (или абсолютно) ациклической (ANC- грамматикой или SNC-грамматикой), если существует такое семейство частичных порядков {/?(У) : X еУ}, что справедливы следующие два условия: П ацикличность для любой продукции р е Р является ациклическим R(Xi)^...^R(Xn{r})^D(p)- П замкнутость для любой продукции р ЕР — ограничение отношения [7?(У|)и.. и Р(У„^) и £>(р) ]+ на А(Х0) является подмножеством Р(У0),т. е. [ &(%,) и... u R(Xn{p})vD(p)] +Хи с R(X(I). А. Существует полиномиальный алгоритм для вычисления семейства минимальных R(X) для сильно ациклических грамматик. Два следующих примера иллюстрируют строгое включение класса /-упорядоченных грамматик в класс SVC-грамматик и класса S/VC-грамматик в класс ациклических грамматик. Грамматика, правила которой изображены на рис. 8.14, а, является ациклической, поскольку каждое из двух возможных деревьев R(t) не содержит циклов. Однако грамматика не абсолютно ациклическая, поскольку, построив R(X) (см. рис. 8 14,6), получаем цикл в первом слева правиле. Грамматика, правила которой изображены на рис. 8.15, а, является УУС-грамматикой. Построив R(X) (см. рис. 8 15, б), можно убедиться в отсутствии циклов в любом пра-
Глава 8. Контекстный анализ 607 виле. Условие замкнутости также тривиально удовлетворяется. С другой стороны, совместное рассмотрение О1(Х) (см. рис. 8.15, в) и R(X) дает по крайней мере зависи- мости, изображенные на рис. 8.15, г, а они содержат цикл. Это означает, что грамма- тика не является /-упорядоченной. Этот факт подтверждает также то, что нет общего порядка, не противоречащего частичным порядкам каждого из двух возможных де- ревьев. R(X)=IO(X)= б) Рис. 8.14. Ациклическая грамматика: а— правила грамматики, б— R(X) OI(X)= abed R(X)=IO(X)= Рис. 8.15. Сильно ациклическая грамматика: а — правила грамматики, б — R(X), в — О1(Х), г — зависимости Пусть Use(A, а) обозначает множество синтезируемых атрибутов у X, от которых за- висит а, т. е. Use^Y, d) = {b : b G 1(Х) и (Ь, а) е R+(X)}. Наиболее интересной характеристикой грамматики, принадлежащей к классу SNC, является то, что реальные зависимости между наследуемыми и синтезируемыми ат- рибутами, индуцированные RJJ) в дереве t с корнем X, покрываются R(X) (это свой- ство следует из Ю(Х) g R(X)). Отсюда любой синтезированный атрибут а, ассоциированный с нетерминалом X, может рассматриваться как функция от дерева с корнем X и атрибутов Use(Az, а). Це- ликом атрибутная грамматика эквивалентна множеству функций, рекурсивно опре- деленных над структурой дерева t. Справедливо более общее свойство.
608 Часть II. Применение графов и граф-моделей Б. Любая ациклическая грамматика может быть описана в виде системы рекурсив- ных функций с неподвижной точкой или без неподвижной точки. Одно из преимуществ вычислителя SNC — то, что он нисходящий. Однако поскольку часто Ю(Х) с R(X), он будет вычислять слишком много наследуемых атрибутов, т. е. вычислять множество Useful,//), более широкое, чем Useful/?rf (/). Кроме того, его временная сложность является экспоненциальной от размера И//), если не поддержи- вается информация о вычисленных переменных (та же ситуация, что и для S-грам- матик). Конечно, это не допустимо, и существуют реализации, сохраняющие значе- ния синтезируемых атрибутов, но перевычисляющие значения наследуемых атрибу- тов. В этом случае SMC-вычислитель не может быть оптимальным по времени, даже если все атрибуты являются полезными, поскольку коэффициент пропорционально- сти больше 1. Некоторые экспериментальные исследования SNC- и /-упорядоченных грамматик показали их сравнимость на практике. Можно оценить динамический размер SMC-вычислителя, сохраняющего только дере- во t, синтезируемые атрибуты из W(t) и стек рекурсивных вызовов, чья максимальная глубина определяется высотой дерева, но содержит в каждом элементе столько ин- формации, сколько наследуемых атрибутов в соответствующем множестве Use(M, а). Статический размер SMC-вычислителя зависит от способа кодирования информации. Но он может рассматриваться как линейная от размера графа ^...иЦХ^иЦр); и, следовательно, как полиномиальная функция от размера грамматики. 8.4.4.,Вычислители для грамматик общего вида Поскольку каждая ациклическая грамматика может быть преобразована в SNC- грамматику, SMC-конструктор можно применить для построения нисходящих опти- мальных по времени вычислителей для ациклических грамматик. Вычислитель стро- ится выполнением следующих двух фаз: 1. Восходящее вычисление отношений sd(X„~) для каждой вершины и дерева t. 2. Нисходящее вычисление (оптимальное по времени, если все значения W(t) сохра- няются в соответствии с SMC-методом). Достаточно выбирать функции для ис- пользования во время предыдущей фазы. Второй метод состоит в построении общего порядка T(f) во время двух предвари- тельных фаз и затем в применении метода /-упорядочения. Вычислитель проходит через следующие три фазы: 1. Восходящее вычисление отношений sd(Xu) для каждой вершины и дерева I. 2. Нисходящее вычисление отношений id(X„) для каждой вершины и дерева t и пре- образование порядка в некоторый общий порядок. 3. Восходящее оптимальное по времени (если все атрибуты являются полезными) вычисление, использующее метод /-упорядочения.
Гпава 8. Контекстный анализ 609 Указанный подход основывается на том свойстве, что любая ациклическая грамма- тика может быть преобразована в /-упорядоченную. Оба подхода могут быть эффективными, если все возможные отношения sd, и idt вы- числяются заранее, т. е на этапе конструирования вычислителя; в противном случае, могло бы стать существенным время конструирования плана. Но при любом подходе экспоненциально увеличивается размер преобразованной грамматики, и то же самое может быть для статического размера вычислителя. Это объясняет то, почему ука- занные подходы пока не находят своего применения на практике. 8.4.5. Восходящее вычисление для S-атрибутных грамматик Синтезируемые атрибуты могут вычисляться при восходящем разборе во время ана- лиза входной цепочки. Анализатор может сохранять на своем стеке значения синте- зируемых атрибутов, ассоциированных с грамматическими элементами Когда осу- ществляется редукция, значения новых синтезируемых атрибутов вычисляются по атрибутам, находящимся на стеке для грамматических символов правой части реду- цируемой продукции. Рассмотрим, как стек разбора может быть расширен для хране- ния значений этих синтезированных атрибутов. Транслятор по S-атрибутной грамматике может быть часто реализован с помощью L//-конструктора. По S-атрибутной грамматике конструктор анализатора может по- строить транслятор, который вычисляет атрибуты, когда он разбирает вход. Восходящий (или горизонтальный) анализатор использует стек для хранения инфор- мации о поддеревьях, которые уже проанализированы. Можно использовать допол- нительные поля в стеке анализатора для хранения значений синтезируемых атрибу- тов. Рис. 8.16 дает пример стека разбора с местом, отведенным под одно значение атрибута. Предположим, как это показано на рисунке, что стек реализуется в виде двух массивов: состояние и значение. Каждый вход массива состояние является ука- зателем (или индексом), связанным с элементом таблицы /7?(1)-разбора (заметим, что символ грамматики включается в состояние и не нуждается в сохранении на стеке). Однако удобно ссылаться на состояние через тот единственный символ грамматик, который оно покрывает, когда размещается на стеке разбора. Если /-й символ масси- ва состояние есть А, то значение{1\ будет хранить значение атрибута, ассоциирован- ное с вершиной дерева разбора, которая соответствует этому А. Верх -> Состояние Значение X Х.х Y Y.y Z Z.z Рис. 8.16. Состояние стека разбора 20 Зак. 202
610 Часть II. Применение графов и граф-моделей Текущий верх стека отмечается указателем верх. Предполагается, что синтезируемые атрибуты вычисляются непосредственно перед каждой редукцией. Пусть семантиче- ское правило A.a '~flX.x, Y.y, Z.z) ассоциировано с функцией A -+XYZ. Перед редукцией XYZ в А значения атрибутов Z.z, Y.y и Х.х находятся в значе- ние[верх], значение[верх —1] и значение[верх— 2] соответственно. Если символ не имеет атрибута, тогда соответствующий элемент массива значение не определен. По- сле редукции верх уменьшается на 2, состояние, покрывающее А, размещается в со- сиюяние[верх] (т. е. на то место, где находился X), и значение синтезированного ат- рибута А.а размещается в значение\верх\. В рассмотренной реализации фрагменты кода выполняются непосредственно перед тем, когда происходит редукция. Редукции обеспечивают "крючки", на которые мо- гут быть "повешены" действия, составляющие произвольные фрагменты кода. Таким образом, пользователю разрешается ассоциировать с продукцией действия, которые выполняются, когда имеет место редукция, относящаяся к этой продукции. 8.5. L-атрибутные грамматики Класс атрибутных грамматик, получивших название Z-атрибутных, позволяет осуще- ствить вычисление атрибутов любого атрибутированного дерева в процессе его об- хода в глубину. 8.5.1. Порядок обхода в глубину и L-атрибутные грамматики Когда процесс трансляции происходит во время разбора, порядок вычисления атри- бутов связывается с порядком, в котором создаются вершины дерева разбора исполь- зуемым методом синтаксического анализа. Естественным порядком, который харак- теризует многие методы восходящей и нисходящей трансляции, является тот, кото- рый получается применением к корню дерева разбора следующей процедуры: проц ВЫЧИСЛЕНИЕ В ГЛУБИНУ(л : вершина) = 1. для каждого сына m вершины п при их обработке слева направо цикл 2. Вычислить наследуемые атрибуты т; 3. ВЫЧИСЛЕНИЕ В ГЛУБИНУ(т) все; 4 Вычислить синтезируемые атрибуты л все Указанный порядок вычисления называют порядком глубины один. Даже если дере- во разбора реально не конструируется, удобно изучать процесс трансляции при раз- боре в терминах вычисления атрибутов у вершин дерева разбора в порядке глубины один. Класс атрибутных грамматик, получивших название /.-атрибутных, состоит из грам- матик, чьи атрибуты всегда могут быть вычислены в порядке глубины один.
Гпава 8. Контекстный анализ 611 Атрибутная грамматика называется L-атрибутной, если каждый наследуемый атри- бут А), где 1 <п, в правой части любой продукции А ->Х2... А,, зависит от: □ атрибутов символов Х\, Х2,..., Ху-Ь находящихся левее X в данной продукции; П наследуемых атрибутов А. Заметим, что каждая S-атрибутная грамматика является L-атрибутной, поскольку условия в определении /.-атрибутной грамматики накладывают ограничения только на наследуемые атрибуты. 8.5.2. Трансляционные схемы Трансляционной схемой называется АС-грамматика, в которой атрибуты ассоцииру- ются с грамматическими символами, а семантические действия, заключенные в скоб- ки { и }, размещены в правых частях продукций. Язык трансляционных схем есть удобная нотация для спецификации трансляции во время разбора. Следующая простая трансляционная схема отображает инфиксную запись констант- ного выражения с операциями сложения и вычитания в постфиксную запись этого выражения: E-+TR, R —> опер Т {вывод(опер.лексема)}Ri\e, Т —> число{выво<5(число.знач)}. Рис. 8.17 содержит дерево разбора для входа 9 — 6 + 3 с указанием семантических действий, приписанных в качестве подходящих сыновей вершин, которым соответст- вуют левые части соответствующих продукций. Фактически здесь рассматриваются действия, как если бы они были терминальными символами; точка зрения, которая дает удобную мнемонику для определения, когда действия должны исполняться. При этом на рис. 8.17 даны фактические числа и операции на местах лексем число и опер. При выполнении операций в порядке обхода дерева в глубину указанные на рис. 8.17 действия напечатают выход 9 6 - 3 +. Когда разрабатывается трансляционная схема, нужно учитывать некоторые ограни- чения, которые гарантировали бы, что значение некоторого атрибута является дос- тупным в момент использования его некоторым действием. Эти ограничения, моти- вированные определением /.-атрпбутности, гарантируют, что действие не ссылается на атрибут, который еще не вычислен. Простейшим является случай, когда все можно сделать только синтезируемыми ат- рибутами. Для этого случая можно конструировать трансляционную схему путем создания действия, состоящего из одного присваивания для каждого семантического правила, и размещения этого действия в конец правой части соответствующей про- дукции. Например, для продукции Т —> Т\ F и семантического правила Т.знач := := Т\3нач Езнач можно построить схему Т > 7'1 F{Tзнач := Т\.знач Fзнач }. Если имеются как наследуемые, так и синтезируемые атрибуты, задача построения схемы несколько усложняется:
612 Часть II. Применение графов и граф-моделей □ наследуемые атрибуты для символов из правой части продукции должны быть вычислены некоторым действием до этого символа; П действие не должно ссылаться на синтезированные атрибуты символов, находя- щихся правее действия; П синтезированный атрибут для нетерминала левой части может быть вычислен только после вычисления всех атрибутов, на которые он ссылается. Действие, вы- числяющее такие атрибуты, может обычно размещаться в крнпе правой части продукции. Рис. 8.17. Дерево разбора для выражения 9-6 + 3 с приписанными семантическими действиями 8.5.3. Удаление левой рекурсии из трансляционной схемы Поскольку большинство арифметических операций ассоциативны слева, естественно использовать для выражений леворекурсивные грамматики. В случае синтезируемых атрибутов можно осуществить преобразование атрибутной грамматики, удаляющее левую рекурсию из грамматики, являющейся основной. Мотивировкой этого преоб- разования является следующий пример. Трансляционная схема из листинга 8.1, а может быть преобразована в трансляцион- ную схему, изображенную в листинге 8.1, б. Новая схема для выражения 9-6+3 строит аннотированное дерево, изображенное на рис. 8.18. Сплошные стрелки на этом дереве указывают путь определения значения выражения. Для нисходящего разбора можно предполагать, что некоторое действие отрабатыва- ется в тот момент, когда раскрывается символ, находящийся в той же самой позиции. Таким образом, во второй продукции в листинге 8.1. б первое действие (присваива- ние R.I) выполняется после того, как Т полностью раскрывается до терминалов, а второе действие осуществляется после полного раскрытия R\.
Гпава 8. Контекстный анализ 613 Листинг 8.1а. Трансляционная jсхема (вариант 1) Листинг 8.1 б. Трансляционная схема (вариант 2) Е -» Ei + Т {Е.знач = Е-^знач + Т.знач} Е -> Е-i - Т {Е.знач := Е^знач - Тзнач} Е-+Т{Е знач ;= Т.знач} Т-> (Е) {Т.знач = Е.знач} Т —> число { Т.знач := число.з//«ч} Е -» Т {R.i = Тзнач}Р{Е.знач := R.s.} R -> + Т{R-\.i .= R.i + Т знач} Ri {R.s. := Ri.s} R ->- T{Ri.i := R i-Tзнач} Ri {R s. = Ri s} R -> e {R.s. := R.i} R -> (E) {Т.знач = Е.знач} Tчисло {Т.знач := число.змач} Рис. 8.18. Атрибутированное дерево Для того чтобы адаптировать другие леворекурсивные схемы к предсказываю- щему разбору, можно представить в более общем виде использование атрибу- тов R.i и Rs в листинге 8.1, а, б. Рассмотрим следующую трансляционную схему: А AiY{A.a := g(A\.a, Tj’)}, А ~^>Х{А.а := flX.x)}. Каждый грамматический символ имеет синтезируемый атрибут, записанный с использованием соответствующей строчной буквы, a f и g— произвольные функции. Алгоритм для удаления левой рекурсии преобразует продукции основы к виду A ->XR, R^YR | е. Учитывая в данном преобразовании и семантические действия, можно получить сле- дующую трансляционную схему A -+X{R.i ~fiX.x}}R{A.a := R.s}, R Y{R'.i := g(R.i, Y.y)}Rt{R.s := 7?bs}, R —> e{R.s := R.i}
614 Часть II. Применение графов и граф-моделей Трансляционная схема использует атрибуты i и s для R подобно тому, как это изо- бражено на рис. 8.18. Для иллюстрации того, что две рассмотренные трансляционные схемы совпадают, можно рассмотреть два аннотированных дерева, изображенных на рис. 8.19. На рис. 8.19, а показан процесс вычисления значения А.а в первой трансля- ционной схеме. Рис. 8.19, б представляет ход вычисления R.i вниз по дереву в соот- ветствии со второй трансляционной схемой. Значение атрибута R.i у листа пересыла- ется в R.s, затем оно становится корректным значением А.а у корня (R.s не показан на рис. 8.19, б). Рис. 8.19. Атрибутное вычисление: а — применение исходной трансляционной схемы, б — применение преобразованной трансляционной схемы Если атрибутную грамматику из табл. 8.1 для конструирования синтаксических де- ревьев конвертировать в трансляционную схему, то продукции и семантические пра- вила для Е примут вид: Е\ + Т {Е.указ := сдверш('+', Е, .указ, Т.указ}}, Е-+ Е\ — Т {Е.указ := сдеерш^—', Е, .указ, Т.указ)}, Е^»Т {Е.указ := Т.указ}.
Гпава 8. Контекстный анализ 615 Применив рассмотренный метод удаления левой рекурсии, можно получить следую- щую трансляционную схему для конструирования синтаксических деревьев: Е-+Т {R.i := Т.указ} R {Е.указ := R.s}, R-+ +Т {R,.i := сдеерш{'+', R.i, Т.указ)} R\ {R.s := Aj-s}, R-+-T {R,.i := cdeepui('~ R.i, Т.указ)} R\ {R s := Ri.s}, R —> e {R.s := R.i}, T —> (£) {Т.указ = Т.указ}, T —> идеи {Т.указ := сдлист(ицен, идеи.вход)}, Т—> число {Т.указ := сд//ыс/л(число, число.знач)}. 8.5.4. Конструирование предсказывающего транслятора --------- Задача----------- Дано. Атрибутная грамматика с основой, являющейся подходящей для предсказы- вающего разбора. Требуется. Сгенерировать код для атрибутного транслятора. --------Решени е----------- Метод. Выполняется следующая последовательность шагов: Шаг 1. Для каждого нетерминала А конструируется функция, которая имеет свой формальный параметр для каждого наследуемого атрибута А и которая возвращает в качестве значения синтезируемые атрибуты А, например, в виде записи (или указате- ля на запись), содержащей свое поле для каждого атрибута, или с помощью исполь- зования параметров, подставляемых по ссылке. Для простоты изложения предполо- жим, что каждый нетерминал имеет в точности один синтезируемый атрибут. В функции для А заводится своя локальная переменная для каждого атрибута каждо- го грамматического символа, содержащегося в продукции для А. Шаг 2 Строится код для нетерминала А, позволяющий решить на основе текущего входного символа, какая должна использоваться продукция в данной ситуации. Шаг 3. Порождается код, ассоциированный с каждой продукцией. Для этого рас- сматриваются лексемы, нетерминалы и действия в правой части продукции слева направо и осуществляются следующие действия: □ для каждой лексемы X с синтезируемым атрибутом х сохраняется значение х в переменной, определенной для Х.х. Затем генерируется вызов по сопоставлению лексемы X и сдвиг по входу; □ для нетерминала В генерируется присваивание с := B(bi, b2,... Ьь) с вызовом функ- ции в качестве правой части, в котором Ь\, Ь2, ... bk— переменные для наследуе- мых атрибутов В, ас— переменная для синтезируемого атрибута В; □ для действия генерируется его копия, в которой осуществлена замена ссылок на атрибуты переменными, соответствующими указанным атрибутам.
616 Часть II. Применение графов и граф-моделей Результирующая грамматика из примера (см. разд. 8.5.3) является LL( I )-грамматикой и, следовательно, подходит для нисходящего разбора. Из атрибутов нетерминалов грамматики получаются следующие типы аргументов и результатов функций для Е, Ш. функ Е: Т вершина_дерева; функ Р(/: t вершина_дерева): Т вершина_дерева; функ Т: Т вершина_дерева; Поскольку Е и Т не имеют наследуемых атрибутов, у них нет аргументов. Листинг8.2. Процедура разбора для R проц R = 1. если следующая = addop то 2. conocmaeumb(addop); Т; R 3. иначе /* ничего не делается */ все все Можно скомбинировать две продукции для R с целью уменьшения размера трансля- тора. Новые продукции используют лексему addop для представления "+" и R —> addop Т {R j Л := сдеерш(ги\дор.лексем a, R.i, Туказ)} R । {7?.л := R, .5} R —> е {R.s := R.i}. Код для R базируется на процедуре разбора, представленный в листинге 8.2. Если следующим читаемым символом является addop, то ею отрабатывается продукция R —> addop ТR путем применения процедуры сопоставить для чтения следующей входной лексемы после addop с последующими вызовами процедур для Т и R. В про- тивном случае процедура ничего не делает в соответствии с продукцией R —> е. Процедура для R, показанная в листинге 8.3, содержит код для вычисления атрибу- тов. Лексическое значение lexval вхождения addop сохраняется в леке, сопоставляет- ся addop, вызывается функция, сопоставленная Т, и полученный результат запомина- ется с использованием указателя указ. Переменная i\ соответствует наследуемому атрибуту R\.i, a .V| — синтезируемому атрибуту R\.s. Функции для Е и Т конструиру- ются аналогично. j Листинг 8.3. Процедура разбора для R с действиями для вычисления атрибутов функ R(i: t вершина_дерева):Т вершина_дерева = 1. перем указ, /7, si, s :t вершина_ дерева 2. если следующая = addop то 3. /* продукция R -> addop TR*I
Гпава 8. Контекстный анализ 617 4. леке := lexval 5. conocTaBHTb(addop); 6. указ := Т, 1. и := сдверш(пекс, i, указ), 8. Si := /?(/,); 9. s := si 10. иначе /* продукция R -> е */ 11 s := / все 12. возврат s все 8.5.5. Удаление встроенных действий из трансляционных схем В восходящем методе, описанном в разд. 8.4.5, все трансляционные действия разме- щаются с правого конца продукции, а в предсказывающем методе из разд. 8.5.4 дей- ствия встраиваются в разные места правой части продукции Вместе с тем существу- ет преобразование, которое позволяет все встроенные действия трансляционной схе- мы перенести на правые концы продукций. Указанная трансформация размещает новые маркирующие нетерминалы, из которых выводится пустая цепочка е в базовой грамматике. Каждое встроенное действие за- меняется на свой (отличный от других) маркирующий нетерминал М, и указанное действие присоединяется к концу продукции М —> е. Например, трансляционная схема Е -> TR, /? —> + Т {вывод{'+')} R | - Т {выводе-')} R | е, Тчисло{еыбод(число.з//о’*/)} преобразуется с помощью нетерминалов Л7 и 7V к виду: Е^> TR, R^> + TMR | - TNR | е, 7—»число {вывод(чпсло.знлч)}, М—> е {eweodf I')}, N—> е {вывод(''—')}. Нетрудно видеть, что в этих двух трансляционных схемах (а также в общем случае применения преобразования) допускается один и тот же язык, и при изображении дерева разбора с внешними вершинами для действий можно убедиться, что действия выполняются в том же самом порядке. Действия в полученной после преобразования трансляционной схеме завершают продукции так, что они могут выполняться непо- средственно перед редуцированием правой части во время восходящего разбора.
618 Часть II. Применение графов и граф-моделей 8.5.6. Наследуемые атрибуты на стеке разбора Восходящий анализатор редуцирует правую часть продукции A —>ХУ путем удале- ния Хи Кс верха стека разбора и заменой их на Л. Предположим, что X имеет синтезируемый атрибут X.s, который реализуется способом, описанным в разд. 8.5.4, за счет сохранения его вместе с X на стеке разбора. Поскольку значение Xs уже находится на стеке разбора перед тем, как имеет место любая редукция в поддереве ниже Y, это значение может наследоваться У. Поэтому если наследуемый атрибут Ул' определяется при правиле копирования Y.i := X.s, то значение X.s может использоваться там, где востребуется Ул. Покажем, что правила копирования играют важную роль в вычислении синтезированных атрибутов во вре- мя восходящего анализа. Тип идентификатора в описании может передаваться с помощью правил копирова- ния, использующих наследуемые атрибуты. Например, для трансляционной схемы: D —> T{L.exod := T.mun}L Т —> int{7’.wi/« := целый} Т —> real {Т. тип := веществ} L —> {L\.exod := L. exod}L\, id {добтип(\&.элемент, L. вход)} L —> id {добтип{\й.элемент, L. вход)} и для входа real р, q, г передача значения атрибута будет имеет вид, как на рис. 8.20, и будет выполнена анализатором последовательность сдвигов, приведенная в табл. 8.2, если игнориро- вать семантические действия и указывать вместо стековых состояний соответствую- щие грамматические символы, а вместо лексемы id — соответствующие идентифика- торы. Рис. 8.20. Схема передачи атрибутов
Гпава 8. Контекстный анализ 619 Здесь, как и в разд. 8.4.5, предполагается, что стек разбора реализуется двумя масси- вами: состояние и значение. При этом если состояние[1\ сохраняет грамматический символ X, то значение[(\ хранит синтезируемый атрибут X.s. Заметим, что каждый раз, когда редуцируется правая часть продукции L (см. табл. 8.2), Т находится в стеке непосредственно ниже правой части. Можно использовать этот факт для доступа к значению атрибута Т.тип. Таблица 8.2. Протокол выполнения сдвигов Вход Состояние Используемая продукция real р, q, г - Р, Ч,г Real Р. Я, г Т T —> real ,q,r тР ,q,r TL Z. —> id Q,r TL , г TL,q , г TL L -> L, id R TL, TL,r TL Z. —> Z., id D D—*TL Реализация, представленная в табл. 8.3, использует тот факт, что атрибут Т.тип на- ходится в стеке значение на известном месте относительно верха. Здесь верх и по- верх — индексы верхнего элемента стека непосредственно до и после имеющей место редукции соответственно. Из правил копирования, определяющих Ь.вход, следует, что Т.тип может использоваться вместо Ь.вход. Таблица 8.3. Продукции и соответствующие фрагменты кода Продукция Фрагмент кода D->TL T —> int значение\новерх] := целый Т -> real значение[новерх] := веществ L —> L, id добтип(значение[верх], значение[верх — 3]) Z. —> id добтип(значение\верх\, значение[верх— 1])
620 Часть II. Применение графов и граф-моделей Когда применяется продукция L —> id, атрибут id.a/z£i/e//w находится наверху стека значение, а Т.тип— сразу под ним. Следовательно, вызов добтип(значение[верх], значение [верх — 1]) эквивалентен вызову добтип(\й.элемент, Т.тип). Аналогично, поскольку правая часть продукции Л —> Л, id содержит три символа, Т.тип находится в значение[ верх — 3], когда отработка этой продукции имеет место. При этом ликвидируются правила копирования, вычисляющие Ь.вход, поскольку вместо его значения используется значение Т.тип, взятое из стека. 8.5.7. Восходящий разбор и трансляция с синтезируемыми атрибутами ---------Задача----------- Д а н о. L — атрибутная грамматика с базовой А£(1)-грамматикой. Требуется. Построить анализатор, вычисляющий значения всех атрибутов на сте- ке разбора. -------Р е ш е н и е------ Метод. Для простоты изложения пусть каждый нетерминал А имеет один насле- дуемый атрибут A.i, а каждый грамматический символ X имеет синтезированный атрибут X.s. Если X является терминалом, тогда его синтезированный атрибут явля- ется фактически лексическим значением, возвращаемым лексическим анализатором вместе с Х\ это лексическое значение появляется на стеке, в массиве значение, как и в предыдущих примерах. Для каждой продукции А —> Х\Х2... Х„ вводится п новых маркирующих нетермина- лов, обозначаемых через Mt,..., М„, и проводится замена указанной продукции на продукцию А —> М\Х\... М„Х„. При этом синтезируемый атрибут Xj.s размещается на стеке разбора в элементе мас- сива значение, ассоциированном сX,, а наследуемый атрибут^./, если он один, раз- мещается в том же самом массиве, но уже ассоциируется с /Ц. Заметить, что, хотя при рассмотренном преобразовании вставка М} перед X, упрощает рассмотрение маркирующих нетерминалов, она имеет нехороший побочный эффект, связанный с возникновением конфликтов разбора в леворекурсивной грамматике; поэтому иногда Л/i может быть исключен. Важным инвариантным свойством является то, что при анализе наследуемый атрибут A.i, если он существует, находится в позиции массива значение непосредственно ни- же позиции для Л/|. Поскольку обычно предполагается, что начальный символ грам- матики не имеет наследуемого атрибута, не возникает проблем для случая, когда на- чальным символом является Л; если же имеется такой наследуемый атрибут, его можно разместить под дном стека. Для того чтобы увидеть, что атрибуты могут быть вычислены необходимым образом во время восходящего анализа, можно рассмотреть два случая. Во-первых, если происходит редукция к маркирующему нетерминалу Л/у, то известна та продукция А М} Х}... МпХ,„ к которой данный маркер принадлежит. Следова-
Гпава 8. Контекстный анализ 621 тельно, известны позиции атрибутов, необходимые для вычисления атрибута X, i: АЛ находится в значение [верх — 2/ + 2], X}.J — в значение [верх — 2/ + 3], Ji,..? — в зна- чение [верх — 2J + 4], Х2.1 — в значение [верх — 2j + 5] и т. д. Поэтому можно вычислить Х,Л и запомнить его в элементе значение[верх + 1], кото- рый становится новым верхом стека после данной редукции. Отметим, что принадлежность базовой грамматики к классу LL(V) существенна, по- скольку без этого свойства нельзя гарантировать, что е редуцируется к одному кон- кретному маркирующему нетерминалу, и, таким образом, нельзя разместить нужные атрибуты и даже узнать, какая продукция должна применяться. Далее, каждая LL(\)- грамматика после введения в нее маркеров остается £/?(1)-грамматикой. Второй случай возникает, когда редуцируется немаркирующий символ, скажем, с помощью продукции А М\Xt... М„Х„. Тогда нужно только вычислить синтезированный атрибут A.s; атрибут А/ уже вычис- лен и расположен в элементе стека, расположенном непосредственно ниже элемента, в котором размещен сам А. При этом атрибуты, необходимые для вычисления A.s, во время редукции являются явно доступными в известных позициях на стеке, в пози- циях A’. ,v. Следующие два приема позволяют уменьшить число маркеров, причем второй из них также ликвидирует конфликты разбора для леворекурсивных грамматик: □ если Xf не имеет наследуемых атрибутов, нет необходимости использовать маркер Мг Конечно, при этом места атрибутов на стеке изменятся, если М, отсутствует, но это изменение легко может быть учтено в анализаторе; П если Х]Л существует, но вычисляется с помощью правила копирования Х}Л := АЛ, то можно убрать М\, поскольку из инвариантного свойства известно, что к нуж- ному моменту значение АЛ будет уже размещено в нужном месте стека, непосредственно ниже 2^, и может использоваться также в качестве Х^Л. 8.5.8. Замена наследуемых атрибутов синтезированными Иногда возможно удалить использование наследуемых атрибутов путем изменения лежащей в основе грамматики. В частности, описание в Паскале может состоять из идентификаторов, за которыми следует тип, например, m, n : integer. Грамматика для таких описаний может ис- пользовать продукции вида Т —> integer | char L —> L пдент |идент Поскольку идентификаторы порождаются из L, но тип не находится в поддереве с корнем L, нельзя ассоциировать тип с идентификатором, используя одни синтези- руемые атрибуты. Фактически, если нетерминал L наследует тип из Т в правой части
622 Часть II. Применение графов и граф-моделей первой продукции, получается атрибутная грамматика, которая не является L- атрибутной, так что основанные на ее свойствах методы трансляции не могут быть осуществлены во время разбора. Решение этой проблемы может состоять в таком преобразовании грамматики, кото- рое включает тип в качестве последнего элемента списка идентификаторов: D -> идент L L —идент L |: Т Т -» integer | char Теперь тип может быть получен как синтезируемый атрибут L.mun. Поскольку каж- дый идентификатор порождается L, его тип может быть внесен в таблицу объектов. 8.5.9. Пример атрибутной грамматики, трудной для обработки Рассмотренный в разд. 8.5.8 прием замены наследуемых атрибутов синтезируемыми может быть расширен на некоторые, но не на все /./^-грамматики. В частности, /.-атрибутная грамматика, приведенная в табл. 8.4, основывается на про- стой LR(])-грамматике, но она не может быть реализована в том виде, как она есть, во время £7?-разбора. Нетерминал L в продукции L -> е наследует счетчик числа символов 1, порожденных S. Поскольку продукция L —> е является первой, которую восходящий анализатор мог бы редуцировать, транслятор в этот момент не может знать число символов 1 во входе Таблица 8.4. Атрибутная грамматика Продукция Семантические правила S^>L I.. счетчик := 0 £| счетчик := L. счетчик + 1 L-+ е еыеод(Ь. счетчик) 8.5.10. Рекурсивные вычислители и обходы слева направо Рекурсивные функции, которые вычисляют атрибуты во время обхода дерева разбо- ра, могут конструироваться по атрибутной грамматике с использованием обобщения методики, описанной в алгоритме (см. разд. 8.5.4). Такие функции позволяют реали- зовывать атрибутные грамматики, которые не могут реализовываться одновременно с разбором. В частности, можно ассоциировать с каждым нетерминалом единствен- ную функцию трансляции, которая посещает сыновей вершины для данного нетер-
Гпава 8. Контекстный анализ 623 минала в некотором порядке (не обязательно слева направо), определяемом продук- цией, поставленной в соответствие этой вершине. В разд. 8.5.4 показано, как /.-атрибутная грамматика, основанная на LL{ ^-грам- матике, может реализовываться путем конструирования рекурсивной функции, кото- рая разбирает и транслирует каждый нетерминал. Все /.-атрибутные грамматики можно реализовать, если подобная рекурсивная функция всегда вызывается для вер- шины, поставленной в соответствие данному нетерминалу в ранее построенном де- реве разбора. Рассматривая продукцию, поставленную в соответствие вершине, функция может определить, какие у нее сыновья. Функция, связанная с нетермина- лом А, берет в качестве аргументов вершину и значения наследуемых атрибутов для А и возвращает в качестве результатов значения синтезируемых атрибутов для А. Детали этого конструирования в точности те же, что и в алгоритме, рассмотренном в разд. 8.5.4, за исключением шага 2, на котором функция для нетерминала решает, какая продукция используется на основе текущего входного символа. Здесь функция реализует оператор выбора для определения продукции, используемой в вершине. Таблица 8.5. Атрибутная грамматика для вычисления размера формулы Продукция Семантические правила S^B В. ширина := 10 S.высота В. высота В -+В,В2 ширина В ширина В2 ширинаВ. ширина В.высота тах(В\.высота, В2.высота) В -» В, индекс В2 В\.ширина := В итрина В2ширина := сжать(В.ширина) В.высота := уменыиитъ(В\.высота, В2 высота) В —> текст В.высота := текст. Ь В.ширина Рассмотрим атрибутную грамматику из табл. 8.5, позволяющую определять ширину и высоту формул, одни из которых могут являться индексными выражениями других и отличаться от них размерами изображений. Нетерминал В имеет синтезируемый атрибут высота. Используя алгоритм конструирования предсказывающего трансля- тора (см. разд. 8.5.4), модифицированный как упомянуто, строится функция В, как в листинге 8.4. J............ ”.......................... ?.............................. Листинг 8.4. Функция для В функ В(п, ширина) = 1. перем шир1, шир2, высА, выс2;
624 Часть И. Применение графов и граф-моделей 2. выбор продукция у вершины п из 3. В —> BiB'2: шир1 = ширина- 4. выс1 := В(сын(п, 1), шир1); 5. шир2 .=ширина; выс2 := В(сын(п, 2),шир2); 6. возврат тах(еыс1, выс2); 7. В—>Bi индекс В'у. шир1 := ширина', выс! =В(сын(п, 1),шир1) 8. шир2 := сжать(ширина)’, выс2 := В(сын(п, 3),шир2), 9. возврат уменьшить(выс1, еыс2); 10. В-* текст'-, возврат ширина * текст b 11. иначе % ошибка % все все 8.5.11. Другие обходы рекурсивных вычислителей Когда доступно явное дерево разбора, можно посещать сыновей вершины в любом порядке, что иногда необходимо. Например, для атрибутной грамматики в табл. 8.6, не являющейся /.-атрибутной, в трансляторе сыновья вершины для одной продукции должны посещаться слева направо, а для другой — справа налево. Таблица 8.6. Атрибутная грамматика Продукция Семантические правила А->1.М L.i := l(A.i) M.i •- rn(L.s) A.s :=flM.s) А -> QR R.i := r(A.i) Q.i -.= q(R.s) A s :=AQ s) Указанный абстрактный пример иллюстрирует мощность использования взаимно рекурсивных функций для вычисления атрибутов у вершин в дереве разбора. Функ- ции не должны зависеть от порядка, в котором создаются вершины дерева разбора. Основным соображением для вычисления во время обхода является то, что насле- дуемые атрибуты вершины вычисляются до первого посещения вершины и что син- тезируемые атрибуты вершины вычисляются до последнего покидания вершины. Каждый нетерминал атрибутной грамматики из табл. 8.6 имеет наследуемый атрибут / и синтезируемый атрибут s. Графы зависимости для ее обеих продукций изображе- ны на рис. 8.21. Правила, ассоциированные с А LM, устанавливают зависимости слева направо, а правила, ассоциированные с А —> QR, — зависимости справа налево.
Гпава 8. Контекстный анализ 625 Рис. 8.21. Графы локальных зависимостей Функция для нетерминала А показана в листинге 8.5 и использует соответствующие функции для нетерминалов L, М, Q и R, а также переменные для атрибутов, имена которых образованы из имен нетерминалов и их атрибутов (например, П и Is — пере- менные, соответствующие L.i и L.s). Листинг 8.5. Функция для нетерминала А функ A(n,ai) = 1 выбор продукция у вершины п из 2. 'A—>LM'I* порядок слева направо */ 3. Н := /(a/); Is := Цсын(п, 1), //); 4. mi = m(ls); ms := М(сын(п, 2), mi); 5. возврат f(ms); 6. A->QR'I* порядок справа налево */ 7. л := r(ai); rs := R(cbiH(n, 2),л); 8. qi := q(rs); qs := Q(cuH(n, ’\),qi); 9. возврат f(qs); 10. иначе % ошибка % все все Код, соответствующий продукции А —> LM, конструируется, как это рассматривалось в разд. 8.5.9. Это означает, что сначала определяются наследуемые атрибуты L, затем вызываются функции, сопоставленные L и вычисляющие синтезируемые атрибуты для L, и затем повторяется данный процесс для М. Конструирование кода, соответст- вующего продукции А —> QR, связано с посещением поддерева для R перед тем, как обработается поддерево для Q. В остальном конструирование кода для этих двух продукций очень похоже. 8.6. Распределение памяти под атрибуты Вопросы распределения памяти под значения атрибутов могут решаться либо во вре- мя трансляции, либо когда транслятор конструируется. Последнее предполагает, что порядок вычисления может быть предсказан заранее и можно отвести память под атрибуты один раз и для всех из них при конструировании транслятора.
626 Часть II. Применение графов и граф-моделей 8.6.1. Вводные замечания В методах распределения памяти под значения атрибутов во время трансляции ис- пользуется информация о графе зависимостей для дерева разбора. Поэтому указанная методика подходит для методов разбора, которые определяют порядок вычисления по графу зависимостей. При заданном (не обязательно обходом в глубину) порядке вычисления для атрибу- тов время существования некоторого атрибута начинается с момента первого вычис- ления атрибута и завершается, когда будут вычислены все атрибуты, которые зависят от данного. Можно сохранять память для хранения некоторого атрибутного значения только на период времени его существования. Для того чтобы подчеркнуть, что указанная методика применима к любому порядку вычисления, она будет демонстрироваться на следующем примере атрибутной грам- матики, которая не является ^-атрибутной. Таблица 8.7. Атрибутная грамматика описаний Продукция Семантические правила D-+TL Ь.вход := Т.тип Т —> int Т.тип := целый Т -ь real Т.тип := веществ к Ь^>Ц,1 /-1 вход := Ь.вход I. вход := Ь.вход Ь->1 1. вход = Ь.вход I —> Ц [num] Ц вход := массив(пхып.знач, I.exod) /—>id добтип(\й.элем, 1, вход) Атрибутная грамматика, представленная в табл. 8.7, является обобщением граммати- ки, рассмотренной в разд. 8.5.6, на описания вида real с[ 10][30]; int х[3], ,у[5] дерево разбора для второго из которых изображено штриховыми линиями на рис. 8.22, а. Здесь, как и раньше, тип, полученный из Т, наследуется Ь и передается вперед всем идентификаторам, входящим в описание. Дуга из Т.тип в Ь.вход показы- вает, что Ь.вход зависит от Т.тип. Указанная грамматика не является /.-атрибутной, поскольку Ь.вход зависит от пшп.зиач и num находится справа от Ц в продукции / —> /j.num.
Гпава 8. Контекстный анализ 627 Рис. 8.22. Схема передачи атрибутов: а — атрибутированное дерево б — граф зависимостей 8.6.2. Распределение памяти под атрибуты во время трансляции Допустим, что есть последовательность регистров для хранения атрибутных значе- ний и что любой регистр может хранить любое значение. Если атрибуты представ- ляют значения разных типов, тогда можно сформировать группы атрибутов, которые занимают один и тот же объем памяти, и рассматривать каждую группу отдельно. Предположим, что атрибуты вычисляются в порядке, заданном номерами вершин в графе зависимостей на рис 8.22, а, он представлен в явном виде на рис. 8.22, б Заме- тим, что в графе зависимостей не показаны вершины, соответствующие семантиче- скому правилу do6mnn(id эле.мJ.вход), поскольку не отводится память под пустые атрибуты. Однако это семантическое правило не должно вычисляться до тех пор, пока память под l.exod не будет доступна, и алгоритм, определяющий этот факт должен работать с графом зависимостей, содержащим вершины для этого семантического правила. Время существования каждой вершины начинается, когда вычисляется ее атрибут, и завершается, когда ее атрибут используется последний раз. Например, время сущест- вования вершины 1 кончается, когда вычисляется вершина 2, поскольку вершина 2
628 Часть II. Применение графов и граф-моделей является единственной, на которую влияет вершина I. Время существования верши- ны 2 кончается, когда вычисляется вершина 6. В листинге 8.6 показан метод для вычисления атрибутов, который использует так мало регистров, как это возможно. Рассматриваются вершины графа зависимостей D для дерева разбора в том порядке, в котором они должны вычисляться. Сначала име- ется пул регистров гь г2 .. Если атрибут Ь определяется с помощью семантического правила b '.=flc\, с2,..., с*), то время существования одного или больше из щ, с2,..., с* может кончиться при вычислении ft; регистры, сохраняющие такие атрибуты, воз- вращаются в пул после вычисления Ь. Всегда, когда это возможно, Ь вычисляется в регистре, который ранее использовался для хранения одного из сь с2,..., ск. ; Листинг 8.6. Экономный по памяти метод вычисления атрибутов для каждой вершины m из пн, т2, .... mN цикл 1. для каждой вершины п, чье время существования кончается с вычислением m цикл 2. если некоторый регистр г отмечен то 3. Снять метку с г, Вычислить m в регистре г, 4. Возвратить помеченные регистры в пул 5. иначе % нет отмеченных регистров % 6. Вычислить m в некотором регистре из пула; все; 7. % действия использующие значение m могут размещаться здесь % 8. если время существования m закончилось то 9. Возвратить регистр из-под m в пул все все все На рис. 8.23 показаны регистры, используемые во время вычисления графа зависимо- стей на рис. 8.22. Сначала вычисляется вершина 1 на регистре Время существова- ния вершины 1 заканчивается, когда вычисляется вершина 2, и поэтому вершина 2 вычисляется в гк. Вершина 3 получает свободный регистр г2, поскольку значение вершины 2 будет использовать вершина 6. Рис. 8.23. Регистры, используемые во время вычисления атрибутов по графу зависимостей
Глава 8. Контекстный анализ 629 8.6.3. Удаление копирований Можно улучшить метод, представленный в листинге 8.6, рассматривая правила ко- пирования в качестве специального частного случая. Правило копирования имеет вид b := с, так что если значение с на регистре г, то значение b уже существует на регист- ре г. Число атрибутов, определяемых правилами копирования, может быть значи- тельным, и поэтому желательно избегать явных копирований. Множество вершин, имеющих одно и то же значение, формирует класс эквивалент- ности. Метод, приведенный в листинге 8.6, можно модифицировать следующим об- разом для того, чтобы он хранил значения классов эквивалентности в регистрах. Ко- гда рассматривается некоторая вершина т, сначала проверяется, не определяется ли она с помощью правила копирования. Если это так, то ее значение уже находится на регистре, и т добавляется к классу эквивалентности вершин со значениями на этом регистре. Более того, регистр возвращается в пул только в конце времени существо- вания всех вершин со значениями в этом регистре. Рис. 8.24. Уточненный граф зависимостей Граф зависимостей (см. рис. 8.22) изображен на рис. 8.24 с указанием знака равенства перед каждой вершиной, определенной с помощью правила копирования. Из опреде- ления табл. 8.7 видно, что тип, определенный у вершины 1, копируется в каждый элемент из списка идентификаторов, что приводит к тому, что в вершины 2, 3, 6 и 7 копируется значение вершины 1. Поскольку вершины 2 и 3 являются копиями вершины 1, их значения берутся из ре- гистра Г] (см. рис. 8.24). Заметим, что время существования вершины 3 кончается, когда вычисляется вершина 5, но регистр rh сохраняющий значение 3, не возвраща- ется в пул, поскольку еще не закончилось время существования вершины 2, входя- щей в этот класс эквивалентности. Следующий код показывает, как определение int х[3], у[5] может обрабатываться компилятором: г, := целый; Г вычисляет вершины 1, 2, 3, 6, 7 */ Гг := 5; /* вычисляет вершину 4 */ г2 := массив(г2, и); /* тип у */ добтип(у, г2); г2 := 3; /* вычисляет вершину 8 */ тг := массив(т2, п); /* тип х */ добтип(х, т2);.
630 Часть II. Применение графов и граф-моделей В данном коде х и у обозначают элементы таблицы объектов для х и у, а процедура добпгип должна вызываться в подходящие моменты для добавления типов х и у к со- ответствующим элементам таблицы объектов. 8.6.4. Распределение памяти во время конструирования транслятора Когда порядок вычисления для атрибутов получен по конкретному обходу дерева разбора, можно предсказать времена существования атрибутов во время конструиро- вания транслятора. Например, пусть сыновья посещаются слева направо во время обхода в глубину, как это рассмотрено в разд. 8.5. Начинается обход с вершины для продукции А —> ВС, далее посещается поддерево для В, затем обрабатывается подде- рево для С и потом происходит возврат к вершине для А. Предок А не может ссы- латься на атрибуты В и С, так что их времена существования должны закончиться, когда происходит возврат к А Заметим, что указанные свойства базируются на самой продукции А —> ВС и на том порядке, в котором посещаются вершины для этих не- терминалов, и никак не зависят от вида поддеревьев В и С. При любом порядке вычисления, если время существования атрибута с содержится во времени Ь, и b и с не являются атрибутами одного нетерминала, то значение с мо- жет сохраняться в стеке над значением Ь. В частности, для продукции А ВС можно следующим образом использовать стек во время обхода в глубину. Начинается обработка с вершины для А в ситуации, когда наследуемые атрибуты А уже находятся в стеке. Затем вычисляются и помещаются в стек значения наследуе- мых атрибутов В. Эти атрибуты сохраняются в стеке, пока осуществляется обход поддерева В, в результате которого над ними размещаются вычисленные синтези- руемые атрибуты В. Этот процесс повторяется с С, т. е. сначала размещаются его наследуемые атрибуты, затем обходится соответствующее ему поддерево и происхо- дит возврат с размещением его синтезируемых атрибутов на верху стека. Обозначая через 1(Х) и S(X) наследуемые и синтезируемые атрибуты X соответственно, стек можно представить в виде 1(A), 1(B), S(B), 1(C), S(C). Все значения атрибутов, необходимые для вычисления синтезируемых атрибутов А, к данному моменту уже находятся в стеке, так что можно возвратиться к А со стеком, содержащим 1(A), S(A). Итак зафиксировано число (и вероятно, размер) наследуемых и синтезируемых атри- бутов грамматического символа. Таким образом, на каждом шаге описанного про- цесса известно, где в стеке находится атрибут. 8.6.5. Пример генерации промежуточного представления Рассмотрим реализацию атрибутной грамматики, специфицирующей генерацию про- межуточного представления для фрагмента логических выражений без побочных эффектов. Значение логического выражения Е and F равно ложь, если Е ложно, и поэтому подвыражение F не нужно вычислять, если Е имеет значением ложь.
Гпава 8. Контекстный анализ 631 Таблица 8.8. Атрибутная грамматика для фрагмента логических выражений Продукция Семантические правила Е -> Et and £2 Ех. истина := новая_метка Ei. ложь := Е.ложь Е2. истина ;= Е.истина Е2ложь := Е.ложь Е.код := Ei код || ген('1аЬеГЕ| истина) ||Е2.кой Е —> id Е.код :=ге/дЧГ id. место 'goto' Е. истина) || ?ew('goto' Е.ложь) Рассмотренное в табл. 8.8 атрибутное определение связано с логическим выражени- ем, которое конструируется из идентификаторов и операции and. Каждое выражение Е наследует две метки Е.истина и Е.ложь, отличающие те места кода, куда осущест- вляется передача управления, если Е истинно или ложно соответственно. Пусть £ ^ Е, and £2. Если Е\ вычисляет ложь, то передается управление по наследуемой метке Е.ложь', иначе, если значением Et является истина, переход осуществляется на код, вычис- ляющий значение выражения Е2. Новая метка, генерируемая с помощью функции новая_метка, отмечает начало кода для Е2. Отдельные команды формируются с ис- пользованием ген. Данная атрибутная грамматика Z-атрибутная, и для нее может быть построена транс- ляционная схема (листинг 8.7, в которой вызывается процедура выделить для генера- ции и выделения кода по частям), как это описано в разд. 8.5. Листинг 8.7. Трансляционная схема с одним стеком Е -»{втолкнуть{новая_метка, истина)} Ei and {вь/0елить('1аЬеГ верх(истина)); вытолкнуть{истина)} Е2 Е -> id {выделить('И id.место 'goto' верх(истина)); выделить('дсЛо' верх( ложь))} Трансляционная схема в листинге 8.8 идет дальше: она использует отдельные стеки для хранения значений наследуемых атрибутов Е.истина и Еложъ. i Листинг 8.8. Трансляционная схема с отдельными стеками для атрибутов Е -> {втолкнуть(новая_метка, истина)} E-i and {еыделоть('1аЬеГ верх( истина)); вытолкнуть(истина)} Е2
632 Часть II. Применение графов и граф-моделей Е -> id {выделить ('if id место 'goto'eepx(истина))-, выделить!,'goto' верх{ ложь))} В трансляционной схеме из листинга 8.8 правила копирования не влияют на стек. Для реализации правила Е\.истина := новаяметка новая_метка помещается на истинный стек перед тем. как посещается Е\. Время су- ществования этой метки кончается вместе с действием выде.7гпяь('1аЬеГ eepx(ucimiiia)). соответствующим выйе.71Щ7ь('1аЬеГ Е^истнна), так что истинный стек опускается после этого действия. Ложный стек не изменяется в рассмотренной здесь части трансляции, но это изменение станет необходимым, когда в логическом выражении наряду с and будет использоваться и or операция. 8.6.6. Неперекрывающиеся времена существования Отдельный регистр является частным случаем стека. Если за каждой операцией втолкнуть следует операция вытолкнуть, то можно использовать регистр вместо стека. В терминах времен существования это формулируется следующим образом: если времена существования двух атрибутов не перекрываются, их значения могут храниться в одном и том же регистре. Таблица 8.9. Атрибутная грамматика для мультикоманд Продукция Семантические правила TR R.i := Т.указ Е.указ := R.s R -> addop Т Rt R.i := cc>ee/7i«(addop. лексема, R.i, Т.указ) R.s := Rt.s Rе R.s := R.i Т —> num Т.указ := ccV»/c/;?(num, num. знач) Атрибутная грамматика табл. 8.9 конструирует синтаксические деревья для мульти- команд. Она взята из трансляционной схемы примера в разд. 8.5.3. Утверждается, что время существования каждого атрибута R кончается, когда вычис- ляется атрибут, который от него зависит. Можно показать, что для любого дерева разбора атрибуты R могут вычисляться в одном и том же регистре г. Следующее рас- суждение типично для анализа грамматик. Индукция проводится по размеру подде- рева с корнем R во фрагменте дерева разбора, изображенном на рис. 8.25.
Гпава 8. Контекстный анализ 633 Рис. 8.25. Атрибутное дерево Наименьшее дерево получается при применении правила R-+e, и тогда R s является копией R.i, так что оба их значения находятся на регистре г. Для большего поддерева продукция, примененная к корню дерева, должна иметь вид R addop Т R\. Трансляционная схема в листинге 8.9 вычисляет атрибуты атрибутной грамматики (рис. 8.25), используя регистр г для хранения атрибутов R.i и R.s для всех вхождений нетерминала R. Листинг 8.9. Трансляционная схема Е -> Т {г •= Т.указ Г г теперь хранит R / */} R {Е указ = г/* г имеет возвращаемое в R.s */} R -» addop T{r .= сдеерш(addop. лексема г, Т.указ)}Е R-+a Т-> num { Т.указ := cdnucm(num, num. знач)} Время существования R / кончается, когда вычисляется так что Rt.i может вы- числяться в регистре г. Из индуктивного предположения следует, что все атрибуты для вхождений нетерминала R в поддерево с корнем могут быть приписаны к од- ному и тому же регистру. Наконец, R.s является копией Rt.s, так что его значение уже в г. Листинг 8.10. Код трансляционной схемы функ Е: Т вершина_дерева = 1. перем г: Т вершина_дерева; оплекс : лексема 2. проц R = 3. если следующая = addop то 4. оплекс := lexval; conocTaBHTb(addop); 5. г := сдверш(оплекс г, Т); R все все; 6. г := Г, R; возврат г все
634 Часть II Применение графов и граф-моделей В листинге 8 10 приведен код для описанной трансляционной схемы; он построен с помощью метода решения задачи генерации кода, описанной в разд. 8.5.4. Нетер- минал R не имеет других атрибутов, поэтому R становится процедурой, а не функци- ей. Переменная г реализована как локальная к функции Е, так что возможно вызы- вать Е рекурсивно, хотя это не является необходимым по схеме листинга 8 9. Данный код в дальнейшем может быть улучшен путем удаления хвостовой рекурсии и затем открытой подстановкой процедур. Библиографический комментарий Использование синтезируемых атрибутов для спецификации трансляции появилось в работе Йронса [32]. Идея разбора путем вызова семантических действий обсуждалась Замельзоном и Бауэром [69], а также Брукером и Моррисом [17]. Совместное их рассмотрение вместе с насле- дуемыми атрибутами графами зависимостей и проверкой сильной ацикличности было выпол- нено Кнутом [47] (тест для цикличности появился в исправлениях к данной статье; см. также [6]). Преобразование грамматики к нормальной форме было предложено Бохманном [14]. Класс сильно ациклических грамматик, впервые рассмотренный в [23], интересен тем, что для грамматик такого вида простой вычислитель может быть автоматически построен, а также тем. что алгоритм проверки принадлежности грамматики этому классу имеет полиномиальную сложность По этим причинам указанный класс используется в системах построения трансля- торов и изучается во многих работах [14, 20, 23, 31, 45, 68]. Существует ряд критериев, харак- теризующих указанный класс в терминах существования специальных графов, связь между которыми исследовалась в [29]; там же рассматривается более узкий класс так называемых вдвойне ациклических грамматик (£ЖС-грамматики), для которого строится инкрементальный вычислитель методом, аналогичным используемому для сильно ациклических грамматик. Возможность преобразования любой ациклической грамматики в абсолютно ациклическую показана Катаямой [43]. Эквивалентность класса атрибутных грамматик множеству функций, рекурсивно определен- ных над структурой дерева разбора, показана в [23]. Кеннеди и Уоррен [45] описали итератив- ную версию такого вычислителя. То, что любая ациклическая грамматика может быть пред- ставлена в виде системы рекурсивных функций с неподвижной точкой (соответственно без неподвижной точки), показано в [18] (соответственно в [56]). Определение /.-атрибутной грамматики, сформулированное Льюсом, Розенкранцем и Стирн- сом в [7, 50], мотивировалось возможностью реализации трансляции во время разбора. Подоб- ные ограничения на атрибутные зависимости при каждом из обходов слева направо глубины один рассматривались Бохманном [14]. Аффиксные грамматики, как они введены Косгером [49], относятся к /.-атрибутным грамматикам. Коскимиес и Рэихэ [48] предположили ограни- чения на /.-атрибутные грамматики для управляемого доступа к глобальным атрибутам. Автоматическое конструирование предсказывающего транслятора (с.м. разд 8.5.4) описано Бохманном и Бардом [15]. Представление о том, что нисходящий разбор дает больше возмож- ностей для трансляции, было опровергнуто Брозголом (В. Brosgol), который в своей диссерта- ции доказал, что трансляционная схема, базирующаяся на ££(1)-грамматике, может моделиро- ваться во время £/?(1) разбора. Независимо Ватт [75] использовал маркирующие нетерминалы, чтобы гарантировать, что значения наследуемых атрибутов появляются на стеке во время вос- ходящего разбора. Позиции правых частей продукций, где могут размещаться маркирующие нетерминалы без потери £/?(!) свойства, рассматривались Пурдомом и Броуном [61] Простое требование, чтобы наследуемые атрибуты определялись правилами копирования, не является
Гпава 8. Контекстный анализ 635 достаточным для гарантии вычислимости атрибутов во время восходящего разбора; достаточ- ные условия на семантические правила были найдены Тархио [73]. Некоторое свойство атри- бутов в терминах состояний анализатора, которое может вычисляться во время LR( I) разбора, предложено Джонесом и Мадсеном [37]. Большое число инструментов для реализации атрибутных грамматик создано, начиная со стэнфордской системы FOLDS (declarative formal language difinition system). Система DELTA [52] конструирует граф зависимости во время трансляции. Она распределяет память, рассмат- ривая времена существования атрибутов и удаляя правила копирования. Дерево разбора, осно- ванное на методах вычисления атрибутов, обсуждалось Кеннеди и Раманазаном [44], а также Кохеном и Харри [19]. В [25] описывается более 20 систем, которые связаны с атрибутными грамматиками. Методам вычисления атрибутов и теоретическим основам атрибутных грамматик посвящены обзоры Енгелфрайта [26], Курселя [21, 22], Дерансара, Жордана и Лоро [25], (см. также [I—5, 8—10, 31, 36, 46, 53, 57 — 60, 64, 65, 70, 75]). Система LINGUIST [28] реализует чередующие- ся проходы, впервые рассмотренные Язаери и Волтером [35]. В [30] представлены возможно- сти системы MUG определять по продукции, сопоставленной вершине, порядок посещения сыновей вершины. Система GAG [31] разрешает повторные визиты сыновей вершины; в ней реализован подкласс атрибутных грамматик, введенных Кастенсом [40]. Идея повторных визи- тов появилась в ранней работе Кеннеди и Уоррена [45], в которой были сконструированы вы- числители для широкого класса сильно нециклических грамматик. Реализация, описанная Жорданом [38], конструирует рекурсивный вычислитель для этого класса. Рекурсивные вы- числители конструировались также Катаямой [43]. Совсем другой подход используется Мэд- соном в системе NEATS [55], в которой дэг конструируется для выражений, представляющих атрибутные значения. Анализ зависимостей па этапе конструирования транслятора может уменьшить потребности во времени и памяти на этапе трансляции. Типичной проблемой анализа является проверка грам- матики на цикличность. Язаери, Огден и Раундс [33] показали, что эта проверка требует экпо- пенциального времени в зависимости от размера грамматики. Методы, направленные на улучшения проверки на цикличность, рассматривались многими авторами, включая Лоро и Пеиром [54], Рейха и Саарена [63], Дерансара, Жордана и Лоро [24]. УР-полнота проблемы нахождения топологической сортировки графа зависимости, минимизи- рующей количество используемых регистров, показана Сети [71]. Анализ времен существова- ния в многопросмотровом вычислителе рассматривался Язаери и Позефски [34], а также Кас- тенсом [40], которым были сформулированы условия для реализации атрибутов глобальными переменными и для отображения атрибутов на глобальные стеки. В работе [ 16] описана идея использования различных стеков для храпения синтезируемых и наследуемых атрибутов во время одного прохода. Большинство исследований атрибутных грамматик относится к стратегиям вычислений для "статических" деревьев, т. е. деревьев, которые конструируются анализатором, заполняются значениями атрибутов в соответствии с некоторой заданной атрибутной грамматикой и затем передаются генератору кода. Однако, если ориентироваться на использование атрибутных грамматик в оптимизирующих трансляторах или в системах конструирования программ, воз- никает необходимость исследования стратегий вычислений для "динамических" деревьев, в частности преобразований атрибутированных деревьев и перевычислений (или инкременталь- ных вычислений) значений атрибутов. Различные аспекты работы с динамическими деревьями рассматриваются в [3, 12, 13, 39, 51, 66, 67, 74, 76—78]. Многие из рассмотренных в данной главе алгоритмов и методов описаны Ахо, Сети и Ульма- ном [10] и Дерансарам, Жорданом, Лоро [25].
636 Часть II. Применение графов и граф-моделей Список литературы 1. Бирюков А. Н., Курочкин И. М., Серебряков В. А. Структурные атрибуты и их реализация в системе построения трансляторов СУПЕР // Программирование.— 1981.— №2.— С. 52—55. 2. Вооглад А. О., Меристе М. Б. Абстрактные атрибутные грамматики // Программирова- ние. — 1982. — № 6. — С. 17—26. 3. Касьянов В. Н. Оптимизирующие преобразования программ.— М.: Наука. Сибирское отд-ние, 1988. 4. Касьянов В. Н., Поттосин И. В. Методы построения трансляторов. — Новосибирск: Нау- ка, 1986. 5. Кнут Д. Э. О переводе (трансляции) языков слева направо // Языки и автоматы. — М.: Мир, 1975.— С. 9^12. 6. Кнут Д. Э. Семантика контекстно-свободных языков // Семантика языков программиро- вания.— М.: Мир, 1980. — С. 137—161. 7. Льюис 11., Розенкранц Д., Стирнз Р. Атрибутные трансляции // Семантика языков про- граммирования.— М.: Мир, 1980. — С. 162—195. 8. Пеньям Я. Э. Синтез семантического процессора по атрибутной грамматике // Програм- мирование.— 1983. — № 1. — С. 50. 9. Пакштас А., Золотарев Н. В. Синтаксически-ориентированные компоненты распределен- ных систем. — М.: Наука, 1992. 10. Ахо А. V., Sethi R., Ullman J. D. Compilers: Principels, techniques and tools. — Addison.— Wesly Publ.Company, MA, 1988. 11. Alblas H. Finding minimal pass sequences for attribute grammars // SIAM J. Comput.— 1985.— Vol. 14, N4. — P. 889—914. 12. Alblas H. Iteration of transformation passes over attributed program tree // Acta Informatica. — 1989. — Vol. 27, N 1. — P. 1^10. 13. Babich W. A., Jazayeri M. The method of attributes for data flow analysis (part 1 and 2) // Acta Informatica. — 1978. — Vol. 10. — P. 245—272. 14. Bochmann G. V. Semantic evaluation from left to right // Comm. ACM.— 1976.— Vol. 19, N 2. — P. 55—62. 15. Bochmann G. V., Ward P. Compiler writing system for attribute grammars// Computer J.— 1978. — Vol. 21, N 2. — P. 144—148. 16. Branquart P., Cardinael J.-P., Lewi J. et al. An Optimized Translation Process and its Applica- tion to Algol 68 // Leet. Notes Comput.Sci. — 1976. — Vol. 38. 17. BrookerR. A., Morris D. A general translation program for phrase structure languages// J. ACM — 1962, —Vol. 9, N L — P. 1—10. 18. Chirica L. N., Martin D. E. An order-algebraic definition on Knuthian semantics // Math. Sys- tems Theory. — 1979. — Vol. 13, N 1. — P. I—27. 19. Cohen R., Harry E. Automatic generation of near-optimal linear-time translators for non-circular attribute grammars // Sixth ACM Sump, on Principles of Programming Languages. — 1979. — P. 121—134. 20. Combas E., Bartha M. A multi visit characterization of absolutely noncircular grammars // Acta Cybernet. — 1985. — Vol. 7. — P. 19—31.
Глава 8. Контекстный анализ 637 21. Courcelle В. Attribute grammars: theory' and applications // Leet. Notes Comput. Sci.— 1981. — Vol. 107. — P. 75—95. 22. Courcelle B. Attribute grammars: definitions, analysis of dependencies, proof methods // Meth- ods and Tools for Computer Construction. — 1984. — P. 81—102. 23. Courcelle B., Franchi-Zannettacci P. Attribute grammars and recursive program schemes // Theoret. Comput. Sci. — 1982. — Vol. 17, N 2, 3. — P. 163—191, P. 235—257. 24. Deransart P., Jourdan M., Lorho B. Speeding up circularity tests for attribute grammars // Acta Informatica. — 1984, —Vol. 21, —P. 375—391. 25. Deransart P., Jourdan M., Lorho B. Attribute Grammars: Definitions, Systems and Bibliography // Leet. Notes Comput. Sci. — 1988. — Vol. 323. 26. Engelfriet J. Attribute grammars: attribute evaluation methods // Methods and Tools for Com- puter Construction. — 1984. — P. 103—138. 27. Engelfriet J., FileG. Passes, sweeps and visits in attribute grammars // J.ACM.— 1989.— Vol. 36, N 4. — P. 841—869. 28. Farrow R. Generating a production compiler from an attribute grammar // IEEE Software. — 1984, —Vol. I,N4. — P. 77—93. 29. File G. Classical and incremental attribute evaluation by means of recursive procedures // Theo- ret. Comput. Sci. — 1987.— Vol. 53. — P. 25—65. 30. Ganzinger FL, Giegerich R., Moncke IL, Wilhelm R. A truly generative semantics-directed compiler generator// ACM SIGPLAN Notices. — 1982. — Vol. 17, N 6. — P. 172—184. 31. Giegerich R., Wilhelm R. Counter-one-pass features in one-pass compilation: a formalization us- ing attribute grammars // Inform. Processing Letters. — 1978. — Vol. 7, N 6. — P. 279—284. 32. Irons E.T. A syntax directed compiler for Algol 60 // Comm. ACM. — 1961.— Vol. 4, N 1. — P. 51—55. 33. Jazayeri M., Ogden W.F., Rounds W.C. The intrinsic exponential complexity of the circularity problem for attribute grammars // Comm. ACM. — 1975. — Vol. 18, N 12. — P. 697—706. 34. Jazayeri M., Pozefsky D. Space-efficient storage management in an attribute grammar evaluator // ACM Trans. Programming Languages and Systems. — 1981. — Vol. 3, N 4. —P. 388—404. 35. Jazayeri M., Walter K.G. Alternating semantic evaluator // Proc. ACM Annual Conference. — 1975. — P. 230—234. 36. Jones N. D. ed. Semantics Directed Compiler Generation. — Berlin: Springer-Verlag, 1980. — (Leet. Notes Comput. Sci., Vol. 94). 37. Jones N. D., Madsen С. M. Attribute-influenced LR parsing // Leet. Notes Comput. Sci. — 1980. — Vol. 94. — P. 393—407. 38. Jourdan M. Strongly noncircular attribute grammars and their recursive evaluation // ACM SIGPLAN Notices. — 1984. — Vol. 19, N 6. — P. 81—93. 39. Kaiser G. E., Kaplan S. M. Parallel and distributed incremental attribute evaluation algorithms for software development environments // ACM Trans. Software Engineering and Methodol- ogy. — 1993. — Vol. 2, N 1. — P. 47—92. 40. Kastens U. Ordered attribute grammars // Acta Informatica.— 1980.— Vol. 13, N 3.— P. 229—256. 41. Kastens L'. Lifetime analysis for attributes // Acta Informatica.— 1987.— Vol. 24, N 6.— P. 663—651.
638 Часть II. Применение графов и граф-моделей 42. Kastens U., Hutt В., Zimmermann Е. GAG: a practical compiler generator // Leet. Notes Com- put. Sci. — 1982. — Vol. 141. 43. Katayama T. Translation of attribute grammars into procedures // ACM Trans. Programming Languages and Systems. — 1984. — Vol 6, N 3. — P. 345—369 44. Kennedy K., Ramanathan J. A deterministic attribute grammar evaluator based on dynamic sequencing // ACM Trans. Programming Languages and Systems. — 1979. — Vol. 1, N 1.— P. 142—160. 45. Kennedy K., Warren S. K. Automatic generation of efficient evaluators for attribute grammars // Third ACM Symp. on Principles of Programming Languages. — 1976. — P. 32—49 46. Klein E., Koskimies К Parallel one-pass compilation // Leet. Notes Computer Sci — 1990.— Vol. 461 — P. 76—90. 47. Knuth D. E. Semantics of context-free languages // Math. Systems Theory. — 1968. — Vol. 2, N 2. — P. 127—145. Errata: Math. Systems Theory. — 1971,— Vol. 5, N 1. — P. 95—96. 48. Koskimies K., Raiha K.-J. Modelling of space-efficient one-pass translation using attribute grammars // Software— Practice and Experience. —-1983. — Vol. 13, N 2. — P. 119—129. 49. Koster С. H. A. Affix grammars // Algol 68 Implementation. — North-Holland Publ. Co., 1971, —P. 95—109. 50. Lewis P. M., Rosenkrantz D. J., Stearns R. E. Attributed translations // J. Computer Syst. Sci. — 1974. — Vol. 9, N 3. — P. 279—307. 51. Lipps P., MonckeU., Oik M., Wilhelm R. Attribure (re)evaluation in OPTRAN// Acta Infor- matica. — 1988. — Vol. 26, N 3. — P 213—239. 52. Lorho B. Semantic attribute processing in the system Delta // Leet. Notes Comput Sci. — 1977.—Vol. 47.— P 21—40. 53. Lorho В Methods and Tools for Compiler Construction. — Cambridge Univ. Press., 1984. 54. Lorho B., Pair C. Algorithms for checking consistency of attribute grammars // Proving and Im- proving programs I Ed. by G.Huet, G.Kahn. — Ars-et-Senans, Colloque IRIA, Rocquencourt, 1975. — P. 29—54. 55. Madsen O. L. On defining semantics by means of extended attribute grammars // Leet Notes Comput. Sci. — 1980. — Vol. 94. — P. 259—299. 56. Mayoh В. H. Attribute grammars and mathematical semantics // SIAM J. Comput. — 1981.— Vol. 10, N3. — P. 503—518. 57. Nakata I., Sassa M. L-attributed LL( 1 )-grammars are LR( 1 )-attributed // Inform. Processing Let- ters. — 1986. — Vol. 23. — P. 325—328. 58. Op den Akker R., Melichar B., Tarhio J. The hierarchy of LR-attnbuted grammars // Leet Notes Comput. Sci. — 1990. — Vol. 461. — P. 13—28. 59. Peck J. E. L. Algol 68 Implementation. —Amsterdam: North-Holland, 1971. 60. Pohlmann W. LR parsing of affix grammars // Acta Informatica. — 1983. — Vol. 20, N 4.— P. 238—300. 61. Purdom P., Brown C. A. Semantic routines and LR(k) parsers // Acta Informatica. — 1980.— Vol. 14, N4. — P 299—315. 62. Raiha K.-J. Bibliography on attribute grammars // ACM SIGPLAN Notices.— 1980.— Vol. 15, N3. —P. 35—44. 63. Raiha K.-J., Saarinen M. Testing attribute grammars for circularity // Acta Informatica — 1982.—Vol. 17, N 2. — P. 185—192.
Гпава 8. Контекстный анализ 639 64. Raiha K.-J., Ukkonen Е. On the optimal assignment of attributes to passes in multi-pass attribute evaluators // Leet. Notes Comput. Sci. — 1980. — Vol. 85 — P. 500—511. 65. Raiha K.-J., Ukkonen E. Minimizing the number of evaluation passes for attribute grammars // SIAM J. Comput. — 1981. — Vol. 10, N 4. — P. 772—786. 66. Reps T. W. Incremental evaluation for attribute grammars with unrestricted movement between modifications // Acta Informatica. — 1988 — Vol. 25, N 2. — P. 155—178. 67. Reps T. W., Teitelbaum T., Demers A. Incremental context-dependent analysis for language based editors // ACM Trans. Programming Languages and Systems. — 1983. — Vol. 5. N 3. — p 449—477 68. Nelson H. R. Computation sequences: a way to characterize subclasses of attribute grammars // Acta Informatica. — 1983. — Vol. 19, N 3. — P. 255—268. 69. Samelson K., Bauer F.L. Sequential formula translation // Comm. ACM.— 1960.— Vol. 3, N 2. — P. 76—83 70. Sassa M., Ishizuka H., Nakata I. A contribution to LR-attributed grammars // J. Inform. Process- ing. — 1985. — Vol. 8. — P. 196—206. 71. Sethi R. Complete register allocation problems // SIAM J. Computing.— 1975.— Vol. 4, N 3 P. 226—248. 72. Swiersta S. D., Vogt H. H., Kuiper M. F Higher order attribute grammars // Proc. SIGPLAN'89 Symp. on Programming Language Design and Implementation. — 1989. — P. 131—145. 73. TarhioJ. LR parsing of some ambiguous grammars // Inform. Processing Letters.— 1982.— Vol. 14, N3. — P. 101 103. 74. Vogt H_, Van der Berg A., Freije A. Rapid development of a program transformation system with attribute grammars and dynamic transformation П Leet. Notes Comput. Sci.— 1990.— Vol. 461—P. 101—114. 75. Watt D.A. The parsing problem for affix grammars // Acta Informatica.— 1977.— Vol. 8, N L —P. 1—20 76. Wilhelm R. Tree transformations, functional languages and attribute grammars H Leet. Notes Comput. Sci. — 1990. — Vol. 461. — P. 116—129. 77. Wilhelm R. Computation and use of data flow information in optimizing compiler // Acta Infor- matica. — 1979 - Vol 12, N 3. — P 209—225. 78. Yeh D. On incremental evaluation of ordered attribute grammars // BIT. — 1983. — Vol. 23. — P. 308—320.
ГЛАВА 9 Кодогенерация Одной из наиболее трудных задач, с которыми сталкивается разработчик транслято- ра, является задача построения генератора объектного кода, который по разобран- ной входной программе должен осуществлять кодогенерацию — построение эквива- лентной ей выходной (объектной) программы. Это связано не только со сложностью соответствующих алгоритмов, но и с необходимостью максимально полно учитывать архитектуру конкретной ЭВМ и программную среду, в которой будет работать транслятор. Глава начинается с рассмотрения задачи кодогенерации и описания объектной ма- шины. Затем излагаются основные методы управления памятью периода исполнения, рассматриваются вопросы использования линейных участков и управляющих графов. Описываются методы "простой" кодогенерации и решения задач распределения и присваивания регистров. Рассматриваются методы генерации, основанные на пред- ставлении лучей дэгами и динамическом программировании. Приводятся методы и вопросы покадровой оптимизации и генерации кодогенераторов. Глава завершается решением задачи генерации оптимального кода для стековых машин. 9.1. Задача кодогенерации и объектная машина Имеется большая зависимость кодогенерации от объектного языка и операционной системы. Такие вопросы, как управление памятью, выбор команд, распределение регистров и порядок вычисления, свойственны почти всем проблемам кодогенера- ции. Алгоритмы генерации излагаются в терминах трехадресного кода, деревьев и дэгов, многие из рассмотренных методов применимы также к другим промежуточ- ным представлениям. После рассмотрения задачи кодогенерации описываются трехадресные представле- ния и вид объектных программ, излагаются вопросы управления памятью, распреде- ления регистров и выбора порядка вычисления, а также архитектура используемой объектной машины вместе со стоимостью ее инструкций.
Гпава 9. Кодогенерация 641 9.1.1. Задача кодогенерации Упрощенно процесс трансляции можно представлять себе как последовательное вы- полнение двух фаз — фазы анализа и фазы синтеза (рис. 9.1). Первая фаза включает решение таких задач, как лексический, синтаксический и контекстный анализ. В ре- зультате выполнения первой фазы формируется промежуточное представление ис- ходной программы. Часть транслятора, выполняющая первую фазу, обычно называ- ется первичным (front-end) транслятором. Часть транслятора, выполняющая вторую фазу, называется вторичным (back-end) транслятором. На второй фазе генерируется объектный код и, возможно, формируется загрузочный модуль. Мы будем считать, что объектный код, т. е. выход генератора кода, представляет собой текст на языке ассемблера объектной ЭВМ. Таким образом, генератор кода получает на входе про- межуточное представление исходной программы и переводит его в объектный код, форма которого целиком определяется объектной машиной. Рис. 9.1. Упрощенная схема трансляции Реализация процесса трансляции описанным способом, как правило, приводит к по- лучению программ, существенно уступающих ручным программам по качеству ис- пользования предоставляемых вычислительной системой ресурсов, таких как время, память и т. д. Поэтому часто универсальный способ трансляции дополняется специ- альными приемами и методами, направленными на улучшение качества выходной программы и получивших название оптимизации программ. Проблема построения оптимальной программы алгоритмически не разрешима, и поэтому основная задача оптимизации состоит в удалении неоптимальностей из выходной программы, возни- кающих в ней из-за универсального способа трансляции. При этом основные спосо- 21 Зак. 202
642 Часть II. Применение графов и граф-моделей бы оптимизации транслируемой программы заключаются в удалении вычислений или объектов из процессов выполнений программы или в замене в них сложных вы- числений на более простые. Многие оптимизации можно реализовать, применяя так называемую смешанную стратегию программирования. Суть этого метода состоит в том, что для программи- рования семантически богатой конструкции входного языка (например, цикл или процедура) транслятор использует помимо универсального способа перевода целый ряд специализированных, ориентированных на конкретные, но зато часто встречаю- щиеся в реальных программах варианты использования этой конструкции. Однако обычно оптимизирующие трансляторы используют метод оптимизирующих преобра- зований, который в отличие от смешанной стратегии обладает достаточной языковой независимостью. Рис. 9.2. Схема оптимизирующей трансляции Схема оптимизирующей трансляции изображена на рис. 9.2. Оптимизирующие пре- образования выполняются над транслируемой программой в рамках некоторого ее промежуточного представления и разделяются на машинно-независимые и машинно- зависимые По существу, каждое оптимизирующее преобразование включает в себя: анализ потока данных и потока управления в программе, дающий достоверную ин- формацию о возможных вычислениях по программе, о свойствах ее фрагментов и
Гпава 9. Кодогенерация 643 данных, так называемый потоковый анализ программы, проверку некоторых свойств собранной информации— так называемых контекстных условий; преобразование фрагмента программы в случае удовлетворения этих свойств — собственно onrnuni- зирующее преобразование (трансформация). 9.1.2. Вход кодогенератора На вход кодогенератора поступает некоторое промежуточное представление транс- лируемой программы, которое разделяется на собственно программу, так называе- мый программный массив, и таблицу объектов, содержащую перечень свойств объ- ектов программы, которые представляются в программном массиве входами в табли- цу объектов. Объекты внутреннего языка, в котором представлена промежуточная программа, не являются однородными, а имеют различные атрибуты, важнейшим из которых явля- ется тип. При этом различаются примитивные типы (такие, как целый, литерный и др.) и составные типы, образованные из других типов. Также различаются конст- рукторы (способы организации) составных типов, такие как процедура, запись, ста- тический массив и др. Внутри типа каждый объект может иметь свои атрибуты. В частности, важной характеристикой у переменной является ее класс памяти, т. е. является ли она, например, статической, автоматической, управляемой и т. д. Неоднородность объектов внутреннего представления часто реализуется разбиением таблицы объектов на несколько таблиц, например, в ряде трансляторов отдельно рас- сматриваются таблица имен и таблица констант. Выбор языков представления программного массива достаточно широк. Эти языки представления включают: □ линеаризованные представления, такие как постфиксная или префиксная нотация; П трехадресные представления, такие как четверки, тройки или косвенные тройки; П представления на основе виртуальных машин, такие как код стековой машины; П графовые представления, такие как деревья или дэги. Набор команд внутреннего языка, как правило, шире набора команд обычной ЭВМ. Например, в интересах оптимизации в них ассоциативные операции могут представ- ляться в виде мультикоманд— команд с переменным числом адресов (например, оператор а := Ь + с — d представляется в виде мультикоманды + a, b, с, d~, а оператор х;=у I z*w— в виде мультикоманды *х,у, z~, w, где символ ” указывает на обрат- ную операцию). Предполагается, что до работы кодогенератора произведены лексический и синтак- сический анализы исходной программы и она преобразована в достаточно детальное промежуточное представление, так что значения имен, появляющихся в языке про- межуточного представления, представлены величинами, которыми объектная маши- на непосредственно манипулирует (такими, как биты, целые, вещественные, указате- ли и т. д.). Также предполагается, что выполнен весь необходимый контекстный ана- лиз и все операции преобразования типа вставлены туда, где они необходимы, а также обнаружены очевидные семантические ошибки (например, попытка индекси-
644 Часть II. Применение графов и граф-моделей ровать массив вещественным числом). Таким образом, предполагается, что на входе фазы генерации транслируемая программа уже не содержит контекстных ошибок, хотя нужно заметить, что некоторые трансляторы поиск рассмотренного вида семан- тических ошибок реализуют при кодогенерации. 9.1.3. Трехадресные представления Трехадресный код— это последовательность команд (операторов промежуточного представления) вида х:=у операция z, где х, у, z— имена (или переменные), кон- станты или сгенерированные транслятором временные (рабочие или промежуточ- ные) имена, а операция обозначает любую операцию, такую как, например, операция сложения для целых или операция разыменования для указателей. При реализации трехадресного представления четверками каждая команда представ- ляется в виде записи, состоящей из четырех полей: операция, первый аргумент, вто- рой аргумент и результат. Поле операции содержит внутренний код операции. Опе- раторы с унарными операциями (подобные х := - у или х := у) не используют поле второго аргумента. На рис. 9.3, б изображены четверки для трехадресного кода рис. 9.3, а, полученного из оператора присваивания а := Ь * (- с) + b * (— с), синтак- сические представления которого в виде дерева и дэга изображены на рис. 9.4, а и 9.4, б соответственно. Л := - с t2:-b* г, h := - с r4 := Ь * /3 /5 : 1$ a :=15 a) Номер команды Операция Первый аргумент Второй аргумент Результат (0) uminus с h (1) * h б t2 (2) uminus с h (3) * ь 6 б (4) + h /4 /5 (5) := ts а б) Рис. 9.3. Представление кода четверками: а — трехадресный код, б — четверки для трехадресного кода Чтобы ликвидировать необходимость включения промежуточных имен в таблицу объектов, можно использовать в качестве ссылки на промежуточное значение пози- цию того оператора, который вычисляет его. Если принять такой подход, то трехад- ресные команды можно изображать записями только с тремя полями: операция, пер- вый аргумент и второй аргумент (рис. 9.5). Поля аргументов в таком представлении в виде троек являются указателями либо на определенные программистом имена или константы в таблице объектов, либо на временные значения в таблицу троек. На
Глава 9. Кодогенерация 645 рис. 9.5 числа в скобках — это указатели на тройки, а указатели на элементы таблицы объектов представлены самими именами. Рис. 9.4. Синтаксические представления оператора присваивания: а — в виде дерева, б — в виде дэга Номер тройки Операция Первый аргумент Второй аргумент (0) uminus С (1) * В (0) (2) uminus С (3) * в (2) (4) + (1) (3) (5) := А (4) Рис. 9.5. Представление кода тройками Другой подход к реализации трехадресного кода состоит в построении списка указа- телей на тройки так называемых косвенных троек, вместо списка самих троек. На- пример, для троек, представленных на рис. 9.3, б, указанный подход дает промежу- точное представление, изображенное на рис. 9.6. Различие между тройками и четверками можно рассматривать с точки зрения уровня косвенности, использованного в представлении. Когда в конечном счете порождается объектный код, каждое имя, как временное, так и определенное программистом, бу- дет приписано к некоторой ячейке памяти периода исполнения. Эта ячейка будет помещена в элемент таблицы объектов для указанной величины. При использовании языка четверок трехадресный оператор, определяющий или использующий некото-
646 Часть II. Применение графов и граф-моделей рое временное имя, может непосредственно обратиться за этим временным именем через таблицу объектов. Номер команды Команда (0) (14) (1) (15) (2) (16) (3) (17) (4) (18) (5) (19) Номер тройки Операция Первый аргумент Второй аргумент (14) uminus с (15) * в (14) (16) uminus с (17) * в (16) (18) + (15) (17) (19) := А (18) Рис. 9.6. Представление кода косвенными тройками Более важное преимущество четверок проявляется в оптимизирующих трансляторах, где операторы часто перемещаются. При использовании нотации четверок таблица имен, содержащая временные переменные, вносит дополнительную косвенность ме- жду вычислением значения и его использованием. Если перемещается оператор, вы- числяющий х, то не требуется вносить изменения в операторы, использующие х. В нотации троек, однако, это не так: перемещение оператора, который определяет временное значение, требует изменить все ссылки на этот оператор в полях первого и второго аргументов массива троек. Указанное свойство затрудняет использование троек в оптимизирующих трансляторах. Косвенные тройки не вызывают такого типа проблем. Некоторая команда может пе- ремещаться путем переупорядочения списка команд. Поскольку указатели на вре- менные значения ссылаются на элементы массива, состоящие из полей, которые не изменяются, то ни один из этих указателей менять не требуется. Таким образом, кос- венные тройки и четверки представляются одинаково привлекательными с точки зрения рассмотренных свойств. Указанные две нотации требуют одного и того же объема памяти, и они одинаково эффективны для переупорядочения кода. Как и в случае обычных троек, распределение памяти под те временные имена, которые ну- ждаются в нем, должно быть отложено до фазы кодогенерации. Однако косвенные тройки могут экономить память по сравнению с четверками, если некоторое времен- ное значение используется более одного раза (в двух или более местах массива ко- манд могут быть ссылки на один и тот же элемент). Например, в представлении на рис. 9.6 тройки (14) и (16) можно склеить, что позволяет затем склеить тройки (15) И (17). 9.1.4. Объектные программы Выходом кодогенератора является объектная (или целевая) программа. Подобно промежуточному коду этот выход может принимать разнообразные формы: абсо- лютной машинной программы, перемещаемой программы или ассемблерной про- граммы.
Гпава 9. Кодогенерация 647 Получение машинной программы в абсолютных адресах в качестве выхода обладает тем преимуществом, что указанная программа может размещаться в фиксированных ячейках памяти и непосредственно выполняться. Небольшая программа может быст- ро компилироваться и исполняться. Целый ряд трансляторов для "студенческих про- грамм" (типа WATFIV или PL/С) порождает абсолютный код. Получение в качестве выхода машинной программы в перемещаемой форме (или объектного модуля) позволяет осуществлять раздельную компиляцию подпрограмм. Некоторое множество перемещаемых объектных модулей можно связать вместе и загрузить для выполнения с помощью связывающего загрузчика. Хотя для такого связывания и загрузки потребуются дополнительные расходы, если порождаются перемещаемые объектные модули, есть большое преимущество от гибкости, позво- ляющей раздельную компиляцию подпрограмм и вызов из объектного модуля других ранее скомпилированных программ. Если объектная машина не поддерживает авто- матическую настройку, транслятор должен представлять явную настроечную инфор- мацию загрузчику для связывания отдельно скомпилированных программных сег- ментов. Построение в качестве выхода ассемблерных программ несколько упрощает процесс кодогенерации. Можно генерировать символические команды и использовать макро- средства, помогающие генерации. Цена, которую нужно за это платить, — это до- полнительный шаг ассемблирования после кодогенерации. Поскольку получение ассемблерного кода совсем не дублирует задачу ассемблера, указанный подход пред- ставляется весьма разумным, особенно для машин с небольшой памятью, где транс- лятор вынужден осуществлять несколько проходов. Будем использовать ассемблер- ный код в качестве объектного языка для повышения читаемости. Однако следует отметить, что аналогично тому, как адреса могут быть вычислены по смещениям и другой информации, хранящейся в таблице символов, кодогенератор может порож- дать перемещаемые или абсолютные адреса для имен так же легко, как и символиче- ские имена. 9.1.5. Управление памятью Отображение имен в исходной программе на адреса объектов данных в памяти вре- мени исполнения осуществляется совместно первичным транслятором и кодогенера- тором. Предполагается, что имена в трехадресном операторе ссылаются на вход в таблицу символов для данного имени. Входы в таблице символов создаются в про- цессе обработки описаний в процедуре. Тип в декларации определяет ширину, т. е. объем памяти, необходимый для объявленного имени. По информации из таблицы символов могут определяться относительные адреса для имен в области данных про- цедуры. В разд. 9.2 приводится описание реализаций статического и стекового рас- пределения областей данных и показывается, как имена промежуточного представ- ления могут конвертироваться в адреса объектного кода. Если машинный код генерируется, метки в трехадресных операторах должны быть конвертированы в адреса команд. Этот процесс является вариантом "возвратного хода". Предположим, что метки ссылаются на номера четверок в массиве четверок. В процессе последовательной обработки каждой четверки можно легко получить
648 Часть II. Применение графов и граф-моделей ячейку первой генерируемой машинной команды по текущей четверке, лишь под- держивая счетчик числа слов, использованных для команд, сгенерированных ранее. Этот счетчик может храниться в массиве четверок (в некотором внешнем поле) так, что если встретится при обработке оператор /: GOTO i, где / <J, можно просто гене- рировать команду перехода с целевым адресом, равным машинной ячейке первой команды в коде для четверки I. Однако, если встретился переход вперед, т. е. опера- тор j: GOTO i, где i > j, необходимо сохранить в списке для четверки i место первой машинной команды, сгенерированной для четверки J. Затем, когда процесс обработки достигнет четверки i, происходит размещение в подходящей машинной ячейке команды для перехода вперед к i. 9.1.6. Выбор команд От свойств системы команд объектной машины зависит сложность выбора команд. Важными факторами, влияющими на эту сложность, являются унификация и полнота системы команд. Если объектная машина не поддерживает каждый тип данных в унифицированном виде, тогда каждое исключение из общего правила требует специ- альной обработки. Другими важными факторами являются скорость команд и машинные идиомы. Если не заботиться об эффективности объектной программы, выбор команд является пря- мым. Для каждого типа трехадресной команды можно спроектировать скелет, кото- рый описывает объектный код, генерируемый для этой конструкции. Например, каж- дая трехадресная команда вида х := у + z, где х, у и z статически распределяются, мо- жет транслироваться в последовательность кода MOV у, Ro /* загрузить у в регистр Ro */ ADD z, Ro I* добавить z к Ro */ MOVRo,x /* запомнить Ro в x */ К сожалению, такой вид покомандной кодогенерации часто порождает плохой код. Например, покомандная обработка последовательности команд a := b + с d := a + е будет приводить к генерации следующей последовательности команд MOV b, Ro ADD с, Ro MOV Ro, a MOV a, Ro ADD e, Ro MOV Ro, d в которой всегда является избыточной четвертая команда, а также является избыточ- ной и третья, если контекст таков, что а в дальнейшем не используется.
Глава 9. Кодогенерация 649 Качество сгенерированного кода определяется его скоростью и размером. Объектная машина с богатой системой команд может обеспечивать ряд способов реализации некоторой заданной операции. Поскольку различия в стоимости между различными реализациями могут быть существенными, наивная схема трансляции промежуточ- ного кода может приводить к корректному, но недопустимо неэффективному объект- ному коду. Например, если объектная машина имеет увеличивающую команду (INC), тогда трехадресный оператор a := a + 1 может реализовываться более эффективно с помощью одной команды JNC а вместо того, чтобы использовать очевидную после- довательность, которая загружает а в регистр, увеличивает значение регистра на еди- ницу и затем запоминает результат опять в а’. MOV a, Ro ADD# 1,Я„ MOV Ro, а Учет временных характеристик команд необходим для конструирования хорошего кода, но, к сожалению, обычно достаточно сложно получить точную временную ин- формацию о генерируемых командах. Решение того, какая последовательность ма- шинного кода является наилучшей для данной трехадресной конструкции, может также потребовать знания о контексте, в котором появляется эта конструкция. 9.1.7. Распределение регистров Команды, которые содержат операндами регистры, обычно короче и быстрее тех, которые содержат операнды в памяти. Поэтому эффективное использование регист- ров является особенно важным при генерации хорошего кода. Использование регист- ров часто разделяется на две подпроблемы: I. Во время распределения регистров выбирается множество переменных, которые будут размещаться на регистрах в некоторой точке программы. 2. Во время последующей фазы приписывания регистров подбираются конкретные регистры, в которых помещаются переменные. Нахождение оптимального приписывания регистров к переменным является трудной задачей даже с однорегистровыми значениями. С математической точки зрения эта проблема является Л'/’-полной. На практике проблема еще более усложняется, по- скольку оборудование и/или операционные системы обычно требуют, чтобы соблю- дались определенные соглашения об использовании регистров. Есть машины, которые используют для некоторых операндов и результатов так на- зываемые регистровые пары, каждая из которых образуется из некоторого регистра с четным номером и следующим за ним регистром с нечетным номером. Например, в машинах IBM System 370 целочисленное умножение и целочисленное деление тре- буют регистровых пар. Команда умножения имеет вид Мх, у, где сомножитель х яв- ляется четным регистром четно-нечетной регистровой пары. Значение сомножителя берется из нечетного регистра пары. Множитель у является одним регистром. Резуль- тат умножения занимает целиком четно-нечетную регистровую пару. Команда деле-
650 Часть II. Применение графов и граф-моделей ния имеет вид Dx,y, где 64-битное делимое занимает четно-нечетную регистровую пару, четным регистром в которой является х; у представляет делитель. После деле- ния четный регистр пары хранит остаток, а нечетный — частное. Рассмотрим две последовательности трехадресного кода, представленного на рис. 9.7, которые различаются лишь операциями во втором операторе. На рис. 9.8 для них приведены кратчайшие последовательности ассемблерного кода, R, обозначает регистр с номером I. Команда SRDA Ro, 32, осуществляя операцию SRDA (сдвига вправо двойного арифметического) с аргументами /?0 и 32, сдвинет делимое в /?| и очистит /?0 так, что все его биты станут равны его знаковому биту. Операции L, ST и А используются для загрузки, запоминания и сложения соответственно. Следует за- метить, что оптимальный выбор для регистра, в который а должна загружаться, зави- сит от того, что в конечном счете случится с /. Стратегии для распределения регист- ров см. в разд. 9.5. t:= а + bt:= а + b t:=t*c t:= t + c t := t/d t := t/d Рис. 9.7. Трехадресный код L Rt, a L Ro, а A R-,, b A Ro, b M Ro, c SRDA Ro, 32 D Ro, d D Ro, d STR,, t STRi, t Рис. 9.8. Ассемблерный код 9.1.8. Выбор порядка вычисления Порядок, в котором осуществляются вычисления, может влиять на эффективность объектного кода. Например, для хранения промежуточных результатов одни порядки вычисления требуют меньше регистров, чем другие (см. разд. 9.6). Нахождение наи- лучшего упорядочения является еще одной трудной, ЛТ-полной задачей (см. при- ложение 1). 9.1.9. Архитектура объектной машины Понятно, что знакомство с объектной машиной и ее системой команд является не- пременным условием для проектирования хорошего кодогенератора. К сожалению, в общем обсуждении кодогенерации невозможно описать нюансы какой-нибудь объ- ектной машины с такими деталями, чтобы быть в состоянии генерировать хороший код с полного языка на эту машину. Объектная регистровая машина хорошо отража-
Глава 9. Кодогенерация 651 ет ряд мини-компьютеров и позволяет представить ряд методов кодогенерации, на- шедших уже свое применение для многих других классов машин. Рассмотрим в качестве объектного компьютера побайтово адресуемую машину с че- тырьмя байтами в одном слове и п регистров общего назначения /?0, R}, ..., R„-}. Она имеет двухадресные команды вида операция источник, получатель, в которых поле операция содержит код операции, а источник и получатель являются полями данных. Среди других имеются следующие коды операций: МОУ— переслать источник в получатель, ADD — сложить источник с получателем, SUB — вычесть источник из получателя. Другие команды будут вводиться по мере необходимости. Поля источник и получатель не являются достаточно длинными для хранения адре- сов памяти, так что определенный двоичный код в этих полях специфицирует, какие слова следующей команды содержат операнды и/или адреса. Источник и получатель команды специфицируются путем сочетания регистров и ячеек памяти с видами ад- ресации. В следующем описании содержимое(а) обозначает текущее содержимое регистра или адреса памяти, представленного с помощью а. Виды адресации вместе с их ассемблерно-языковыми формами и ассоциативными стоимостями представлены в табл. 9.1. Таблица 9.1. Виды адресации и связанные с ними дополнительные стоимости команд Вид адресации Форма Адрес Дополнительная стоимость Абсолютная М М 1 Регистровая R R 1 Индексная c(R) с + содержимое! R) 1 Косвенная *R содержимое!/?) 0 регистровая Косвенная *c(R) содержимое(с + содержимое!??)) 1 индексная Литеральная #с С 1 Ячейка памяти М или регистр R представляют сами себя, когда используются в каче- стве источника и получателя. Например, команда MOV Ro, М запоминает содержи- мое регистра в ячейке памяти М. Смещение с от величины, содержащейся в регистре R, записывается как с(/?). Таким образом, команда MOV 4(/?0), М запоминает в ячейке памяти М значение содержи- мое^ + содержим oe(Ro)). Косвенные версии последних двух видов указываются префиксом *. Таким образом, MOV *4(/?0), М запоминает в ячейке памяти М значение содержи.мое(содержимое(4 + содержимое^)))
652 Часть II. Применение графов и граф-моделей Последний вид адресации позволяет источнику быть константой Таким образом, команда МОУ #1, /?(| загружает константу 1 в регистр /?0. 9.1.10. Стоимость команды Предполагается, что стоимость или цепа команды — это увеличенная на единицу сумма стоимостей, ассоциированных с видами адресов источника и получателя. Эта стоимость соответствует длине (в словах) соответствующей команды. Виды адреса- ции, включающие регистры, имеют нулевую стоимость, в то время как другие, с ячейками памяти или литералами в них, имеют стоимость I, поскольку такие операн- ды должны храниться с командами. Если важны вопросы экономии памяти, то следует минимизировать длину команд. Однако такая минимизация уместна и по другим причинам. Для большинства машин и команд время выборки команды из памяти превышает время на ее вычисление; та- ким образом, уменьшая длину команд, мы уменьшаем время, затрачиваемое на вы- полнение команд. Рассмотрим несколько примеров команд. □ Команда МОУ R^, /?, копирует содержимое регистра /?0 в регистр R\. Эта команда имеет стоимость один, поскольку она занимает одно слово памяти. П Команда (запоминания) МОУ R5, М копирует содержимое регистра /?5 в ячейку памяти М. Эта команда имеет стоимость два, поскольку адрес ячейки М находится в слове, следующем за командой. □ Команда ADD #1, R3 добавляет константу 1 к содержимому регистра R3 и имеет стоимость два, поскольку константа 1 должна появиться в следующем слове, рас- положенном после команды. □ Команда SL/B4(R0), *12(/?() запоминает в получателе *12(7?,) значение содержшюфсодержимое(\2 + содержим oe(R^'))— содержимое(содержимое(4 + R)). Стоимость этой команды равна трем, поскольку константы 4 и 12 расположены в двух словах, следующих за командой Некоторые из трудностей генерации кода для рассмотренной машины можно уви- деть, рассматривая, какой код генерируется для команды вида а := Ь + с, где b и с — простые переменные, расположенные в различных ячейках памяти, обозначенных этими именами. Приведем несколько примеров разных способов генерации. 1. MOVb,Rc ADD с, Ro MOV Ro, a стоимость = 6 2. MOVb.c ADD c, a стоимость = 6 Предполагая, что /?(|, Rt и R2 содержат адреса а, b и с соответственно, можно полу- чить 3. MOV * R-\, * Ro ADD * R2. * Ro стоимость = 2
Глава 9. Кодогенерация 653 Видно, что решение задачи генерации хорошего кода для этой машины требует эф- фективного использования возможностей адресации. Имеется определенная выгода от хранения /- или r-значений переменной в регистре, когда это возможно, если предполагается его использовать в ближайшем будущем. 9.2. Управление памятью периода исполнения Семантика процедур языка определяет, как имена связываются с элементами памяти во время исполнения. Информация, необходимая во время исполнения процедуры, хранится в некотором блоке памяти, называемом записью активации', память для имен, локальных по отношению к процедуре, также появляется в записи активации. Рассмотрим код, генерируемый для управления записями активации во время выпол- нения. Следует заметить, что имеются две стандартные стратегии распределения па- мяти: статическое (см разд. 9 2.2) и стековое (см. разд. 9.2.3). При статическом рас- пределении позиция в памяти записи активации фиксируется во время трансляции. При стековом распределении новая запись активации помещается в стек для каждого выполнения процедуры. Указанная запись будет вытолкнута из стека, когда данное исполнение процедуры будет завершено, рассматривается так же (см. разд. 9.2.4), как объектный код процедуры может ссылаться на объекты данных в записях активации. 9.2.1. Вводные замечания Запись активации процедуры имеет поля для хранения параметров, результатов, ин- формации о машинном состоянии, локальных данных, временных переменных и дру- гой подобной информации. В данной главе уделяем основное внимание иллюстрации стратегий распределений, использующих поле машинного состояния для хранения адреса возврата и поля для локальных данных. Поскольку распределение и освобождение записей активации во время исполнения возникает как часть вызова процедуры и кода возврата, при дальнейшем изложении программа выражается в терминах следующих трехадресных команд: □ call — оператор вызова; П return — оператор возврата; □ halt — оператор останова; □ action — любой другой оператор. Например, при указанных соглашениях трехадресный код некоторых процедур сир может иметь вид, изображенный на рис. 9.9. Размер и расположение записей актива- ции передаются кодогенератору через информацию об именах, которая находится в таблице объектов. Для простоты на рис. 9.9 в соответствующих позициях изобра- жаются сами имена вместо ссылок на элементы таблицы объектов, их содержащие. Предполагается, что память периода исполнения разделяется на три области: для ко- да, статических данных и стека (дополнительная область для кучи здесь не рассмат- ривается).
654 Часть II. Применение графов и граф-моделей Трехадресный код /* код для с*/ actionl call action2 halt /* код для р*/ action! return Запись активации Рис. 9.9. Трехадресный код процедур Запись активации 9.2.2. Статическое распределение Рассмотрим код, необходимый для реализации статического распределения. Опера- тор вызова реализуется в промежуточном коде последовательностью двух команд объектной машины. Команда MOV сохраняет адрес возврата, и оператор GOTO пере- дает управление на объектный код вызываемой процедуры MOV #здесь + 20, вызванная.статическая_область GOTO вызванная.область_кода Атрибуты вызванная.статическая область и вызванная.область_кода являются константами, ссылающимися на адреса для вызываемой процедуры соответственно. Источник #здесь + 20 в команде MOV является литеральным адресом возврата; это адрес команды, следующей за командой перехода (в силу правил вычисления стои- мости команд (см. разд. 9.1.10) три константы плюс две команды в вызывающей по- следовательности стоят 5 слов или 20 байтов). Код процедуры заканчивается возвратом к вызывающей процедуре, за исключением первой процедуры, которая не имеет вызывающей процедуры и поэтому ее послед- ней командой является команда останова, которая возвращает управление операци- онной системе. Возврат из процедуры вызванная реализуется следующей командой GOTO * вызванная статическая область, которая передает управление на адрес, запомненный в записи активации. Листинг 9.1. Сгенерированный код процедур /* код для с */ 100: action^ 120: /МОУ #140,364 132: GOTO 200 /* сохранить адрес возврата 140 */ /* вызов р */
Гпава 9. Кодогенерация 655 140 : асИопг 160: HALT 200 : actions 220 : GOTO *364 300: 304 364 : 368: /* код для р 7 /* возврат по адресу из 664 */ /* 300 - 363 хранят запись активации для с */ /* адрес возврата */ Т локальные данные для с */ /* 364 - 451 хранят запись активации для р 7 /* адрес возврата 7 /* локальные данные для р 7 Код в листинге 9.1 конструируется из процедур сир (см. рис. 9 9). Здесь использует- ся псевдокоманда action, которая представляет трехадресный код, не относящийся к данному рассмотрению. В качестве начальных мест расположения кода этих проце- дур произвольно выбраны адреса 100 и 200 соответственно для сида также предпо- лагается, что каждая команда action занимает 20 байтов. Записи активации для про- цедур статически распределены, начиная с ячеек 300 и 364 соответственно. Команды, начинающиеся с адреса 100, реализуют операторы action ц call р; action^, halt первой процедуры с. Следовательно, выполнение начнется с команды action^ с адресом 100. Команда с адресом 120 сохраняет адрес возврата 140 в поле машинно- го состояния, которое является первым словом в записи активации р. Команда GOTO с адресом 132 передает управление первой команде в объектном коде вызванной про- цедуры. Поскольку адрес 140 был запомнен по адресу 364 последовательностью вызова, *364 представляет адрес 140, когда выполняется оператор GOTO по адресу 220. Передача управления возвращается к адресу 140, и выполнение процедуры с продолжается. 9.2.3. Стековое распределение Статическое распределение становится стековым распределением при использовании относительных адресов для запоминания записей активации. Позиция записи для активации процедуры не известна до момента исполнения. При стековом распреде- лении эта позиция обычно хранится на регистре, так что доступ к словам в записи активации может осуществляться по адресу, определенному через смещение от зна- чения этого регистра. Вид индексного адреса, имеющийся в модельной машине, под- ходит для этой цели. Относительные адреса в записи активации могут быть выбраны как смещения от лю- бой известной позиции в записи активации. Для удобства изложения используется
656 Часть II. Применение графов и граф-моделей положительное смещение для поддержки в регистре SP указателя на начало записи активации на верхушке стека. Когда происходит вызов, вызывающая процедура уве- личивает SP и передает управление вызываемой процедуре. После того как управле- ние возвращается вызываемой процедуре, она уменьшает SP и, тем самым, удаляет запись активации вызванной процедуры. Код для обрабатываемой первой процедуры инициирует стек, устанавливая SP на начало стековой области в памяти: MOV#начало_стека, SP /* инициализация стека */ код первой процедуры HALT Г завершение исполнения */ Последовательность вызова процедуры увеличивает SP, запоминает адрес возврата и передает управление вызванной процедуре: ADD #вызванная.размер_записи, SP MOVOadecb + 16, *SP I* сохранение адреса возврата */ GOTO вызванная область_кода Атрибут вызванная.размер записи представляет размер записи активации, так что команда ADD устанавливает указатель SP на начало следующей записи активации. Источник #здесь + 16 в команде MOV является адресом команды, следующей за GOTO, он сохраняется в адресе, на который указывает SP. Последовательность возврата состоит из двух частей. Вызванная процедура передает управление на адрес возврата с помощью команды GOTO *0(SP). Причина использо- вания *0(57’) в команде перехода состоит в том, что требуются два уровня косвен- ности: 0(SP) — адрес первого слова в записи активации, a *0(SP) — адрес возврата, запомненный в этом слове. Вторая часть возвратной последовательности находится в вызвавшей процедуре и осуществляет уменьшение SP путем восстановления в SP предыдущего значения, т. е. после вычитания SP указывает на начало записи активации вызвавшей процеду- ры: SUB вызванная.размер_записи, SP. Пусть имеется программа, состоящая из трех процедур 5, р и q, причем q рекурсивная (листинг 9.2). Листинг 9.2. Трехадресный код для рекурсивной процедуры /‘код ДЛЯ S */ action-t call q actiori2 halt V код для p */ actioni return
Гпава 9. Кодогенерации 657 /* код для q 7 action^ call р actions call q actions call q return Таким образом, несколько активаций q могут существовать одновременно. Также предполагается, что размеры записей активации процедур s, р и q были определены во время трансляции и равны ssize, psize и qsize соответственно. Первые ячейки в каждой записи активации будут хранить адреса возвратов. Коды процедур начинают- ся с адресов 100, 200 и 300 соответственно, а стек начинается с адреса 600. Получает- ся следующий код: /* код для s 7 100 : MOV#600, SP I* инициализация стека */ 108: action 1 128 : ADD #ssize, SP I* начинается последовательность вызова 7 136 : MOV#152, *SPI* поместить в стек адрес возврата 7 144 : GOTO 300 /‘ вызов q 7 152 : SUB #ssize, SP Г восстановить SP */ 160: action2 180: HALT T код для p 7 200: actions 220 : GOTO *0(SP) I* возврат 7 T код для q 7 300 : action^ Г условный переход к 456 7 320 : ADD #qsize, SP 328 : MOV#344, *SP I* поместить адрес возврата 7 336 : GOTO 200 /‘ вызов р 7 344 : SUB #qsize, SP 352 : actions 372 : ADD #qsize, SP 380 : MOV#396, *SP Г поместить адрес возврата 7 388: GOTO 300 396SUB #qsize, SP Г вызов q 7 404: actions 424 : ADD #qsize, SP 432 : MOV#448, *SP I* поместить адрес возврата 7
658 Часть II. Применение графов и граф-моделей 440 : GOTO 300 /* вызов q */ 448 : SUB #qsize, SP 456 : GOTO *0(SP) 600 : I* здесь начало стека *1 Предполагается, что acliotu содержит условный переход на адрес 456 возвратной по- следовательности q; иначе рекурсивная процедура была бы вынуждена всегда вызы- вать саму себя. Рассмотрим исполнение программы, в котором только первый вызов q не делает не- медленный возврат к вызывающей процедуре. Если ssize, psize и qsize равняются 20, 40 и 60 соответственно, то SP при выполнении первой команды по адресу 100 инициализируется числом 600, т. е. начальным адре- сом стека, и хранит число 620 непосредственно перед переходом из s кд. Далее, ко- гда q вызывает р, команда по адресу 320 увеличивает SP до 680, т. е. адреса который начинает запись активации для р; SP возвращается к 620 после возврата к q. Если следующие два рекурсивных вызова q осуществляют возврат без других вызовов, максимальное значение SP во время исполнения равно 680. Заметим, однако, что по- следней ячейкой памяти стека является 739, поскольку запись активации для q, начи- наясь в ячейке 680, занимает 60 байтов. 9.2.4. Адресация периода исполнения для имен Стратегия распределения памяти и размещения локальных данных в записи актива- ции для процедуры определяет, как доступна память для переменных. Часто предпо- лагается, что имя в трехадресном операторе на самом деле является указателем на вход в таблицу символов для этого имени. Такой подход обладает явным преимуще- ством; он делает транслятор более переносимым, поскольку анализирующая часть транслятора не нуждается в изменении, даже если транслятор переносится на другую машину, где требуется другая организация периода исполнения (например, дисплей может храниться в регистрах, а не в памяти). С другой стороны, генерация конкрет- ной последовательности шагов доступа при генерации промежуточного представле- ния может дать заметный выигрыш в оптимизирующем трансляторе, поскольку она позволяет получить преимущество от тех деталей, которые нельзя было бы увидеть в простом трехадресном операторе. В любом случае имена должны по возможности заменяться кодом, описывающим шаги по доступу к соответствующим ячейкам памяти. Рассмотрим более детально процесс обработки простого трехадресного оператора копирования х := 0. Предполо- жим, что после обработки описания в процедуре вход таблицы символов для х со- держит относительный адрес 12. Вначале рассмотрим случай, в котором х находится в статически распределенной области, начинающейся в адресе static. Тогда фактиче- ский адрес перехода исполнения для х является static + 12. Хотя транслятор в конеч- ном счете может определить значение static + 12 во время компиляции, позиция ста- тической области может быть неизвестной, когда генерируется промежуточный код по доступу к имени. В этом случае имеет смысл генерировать трехадресный код для
Гпава 9. Кодогенерация 659 вычисления static + 12 с учетом того, что компиляция будет выполняться во время фазы кодогенерации или, возможно, при загрузке перед исполнением программы. Присваивание х := 0 затем транслируется в static[12] := 0. Если статическая область начинается с адреса 100, объектный код для этого операто- ра будет иметь вид: MOV #0, 112. С другой стороны, можно рассмотреть в качестве входного язык типа Паскаль и ис- пользовать дисплей для доступа к нелокальным именам. Пусть также дисплей хра- нится в регистрах и х локально по отношению к активной процедуре, чей указатель дисплея находится в регистре R3. Тогда можно транслировать оператор копирования х:=0 в последовательность из двух трехадресных команд fi:=12 + /?3 и */( := 0, в которой ц содержит адрес х. Указанная последовательность может быть реализова- на одной машинной командой MOV# 0, 12(/?3). Нужно заметить, что значение реги- стра /?3 нельзя определить во время компиляции. 9.3. Линейные участки и управляющие графы Графовое представление трехадресных операторов, называемое уграфом (или управ- ляющим графом), является полезным для понимания алгоритмов кодогенерации, да- же если граф явно не конструируется тем или иным алгоритмом кодогенерации. Вершины уграфа соответствуют вычислениям, образующим линейные участки, а дуги представляют возможные передачи управления между линейными участками. 9.3.1. Линейные участки и их выделение Линейный участок (или лун) образуется любой последовательностью следующих друг за другом операторов, всегда выполняемых друг за другом в порядке их расположе- ния. Следующая последовательность трехадресных операторов формирует луч: ti := a * a t2 = a* b 6 := 2 * t2 := t\ + /3 t5 := b * b tf> ^4 + ts Говорят, что оператор x :-y + z определяет переменную x и использует переменные у и z (или ссылается на них). Говорят, что некоторая переменная жива (занята или активна) в некоторой точке линейного участка, если ее значение используется после этой точки в программе, возможно, в другом луче. Следующий алгоритм может быть использован для разбиения последовательности трехадресных операторов на лучи.
660 Часть II. Применение графов и граф-моделей Алгоритм 9.1. Нахождения линейных участков Дано. Некоторая последовательность трехадресных операторов. Требуется. Список лучей с каждым трехадресным оператором точно в одном луче. Метод. проц Р-ЛУЧИ= 1. Вначале определяется множество лидеров (или первых операторов) лучей по следующим трем правилам: (а) первый оператор программы является лидером; (6) любой оператор, на который есть передача управления условного или безусловного оператора, является лидером; (в) любой оператор, который непосредственно следует за условным или безусловным оператором перехода, является лидером. 2. для каждого лидера цикл 3. Его линейный участок состоит из данного лидера и всех операторов, следующих за ним. вплоть до, но не включая, следующего лидера или конца программы все все Рассмотренный алгоритм выделяет за линейное время максимальные F-лучи про- граммы, где F— нумерация, соответствующая текстовому представлению програм- мы. Понятно, что эта нумерация не всегда является правильной, т. е. выделяемые максимальные F-лучи не всегда будут максимальными лучами уграфа. Рассмотрим фрагмент исходной программы, представленный в листинге 9.3, который вычисляет скалярное произведение двух векторов а и Ь длины 20. Последователь- ность трехадресных операторов, осуществляющих это вычисление на описанной объектной машине, представлена в листинге 9.4. Листинг 9.3. Фрагмент исходной программы начало 1. х := 0; 2. /:=1; 3. цикл х := х + ф] * Ь[/]; / := / + 1 до / s 20 все; конец j Листинг 9.4. Трехадресный код фрагмента программы (1) х := 0 (2) /:=1 (3) й := 4 * / (4) t2 := а[й] (5) fe:=4 * /
Гпава 9. Кодогенерация 661 (6) t4 := b[f3] (7) t5 := t2 * Д (8) te := x + ts (9) x = k (10) t7:=/+1 (11) /:=t7 (12) если / <20 на (3) Если применить алгоритм 9.1 к трехадресному коду, представленному в листинге 9.4, получим следующее. Оператор (1) является лидером по правилу (а), а оператор (3) — лидером по правилу (б), поскольку на него может передать управление последний оператор. По правилу (в) оператор, следующий за оператором (10) (заметим, что лис- тинг 9.4 содержит только фрагмент программы), является лидером. Следовательно, операторы (1) и (2) формируют луч. Оставшаяся часть фрагмента, начинающаяся с оператора (3), формирует второй луч. Алгоритм 9.2. Нахождения максимальных линейных участков Дано. Уграф G. Требуется. НОМЕР — правильная нумерация уграфа G, а также ВХОДЫ и ВЫХОДЫ — множества входных и выходных вершин максимальных лучей угра- фа G. Метод. проц ЛУЧИ= 1. ПУТЬ : стек= {р0}; ВХОДЫ = {р0}; ВЫХОДЫ = {д0}; 2. НОМЕР = {(ро, 1)} о {(р.О): р^ро); 3. номер := 2; р := р0; 4. обход: начало 5. пока ПРЕЕМ(р) г 0 цикл 6. q:= Э ПРЕЕМ(р); 7. если HOMEP(qo) = О то 8. ПУТЬ <- q; HOMEP(q0) := номер; 9. номер := номер + 1 10. иначе ВЫХОДЫ <-р; 11. ВЫХОДЫ <- НОМЕР'1(НОМЕР(д) - 1) все все; 12. пока ПРЕЕМ(р) = 0 цикл 13. завершить обход при р = ро все; 14. р := Э ПРЕЕМ(р) все; 15. ВЫХОДЫ <- р; 16. начать обход конец;
662 Часть II. Применение графов и граф-моделей 17. для всех ре(ВЫХОДЫ - {q0}) цикл 18. ВЫХОДЫ <- НОМЕР'1(НОМЕР(р) + 1) все все Временная сложность алгоритма 9.2 равна O(/w), m — число дуг уграфа G. 9.3.2. Преобразования на линейных участках Луч вычисляет некоторое множество выражений. Эти выражения являются значе- ниями имен живых на выходе из луча. Говорят, что лучи эквивалентны, если они вычисляют одно и то же множество выражений. Целый ряд преобразований можно применять к лучу без изменения множества выра- жений, вычисляемых лучом. Многие из этих преобразований полезны для повыше- ния качества кода, который в конечном счете будет сгенерирован по линейному уча- стку. Существуют два важных класса таких преобразований: сохраняющие структуру преобразования и алгебраические преобразования. Преобразования, сохраняющие структуру Основными из указанных преобразований линейного участка являются: удаление общих подвыражений, удаление мертвого кода, переименование временных пере- менных, перестановка двух независимых соседних операторов. Эти преобразования рассматриваются в предположении, что лучи не содержат массивов, указателей или вызовов процедур. Удаление общих подвыражений можно проиллюстрировать на следующем примере луча: а := b + с b := a- d с:- Ь + с d:= a — d в котором второй и четвертый операторы вычисляют одно и то же выражение, а именно выражение b + с - d, и следовательно этот луч можно преобразовать в экви- валентный луч а := b + с b:= a -d с := b + с d := b Заметим, что хотя первые и третьи операторы в каждом из рассмотренных лучей имеют одно и то же выражение в правых частях, вторые операторы в лучах переоп- ределяют Ь. Следовательно, значение b в третьих операторах могут отличаться от значения b в первых операторах, т. е. первые и третьи операторы не вычисляют одно и то же выражение.
Гпава 9. Кодогенерации 663 Удаление .мертвого кода. Предположим, что переменная х является мертвой, т. е. в дальнейшем нигде не используется значение переменной х после точки луча, где размешен оператор определения х, например, имеющий вид х =у + z. Тогда этот опе- ратор безопасно может быть удален из луча без изменения значения луча. Переименование временных переменных. Предположим, что в луче имеется оператор tb + с, в котором t— временная переменная. Если заменить этот оператор на опе- ратор и := b + с, где и является новой временной переменной, и заменить все исполь- зования этого вхождения t на и, то значение луча не изменится. В действительности всегда можно перейти от исходного луча к эквивалентному ему лучу, в котором каж- дый оператор, определяющий временную переменную, будет засылать значение в (или определять) новую временную переменную; такой луч называется лучом, нахо- дящимся в нормальной форме. Перестановка операторов. Предположим, что луч содержит два рядом расположен- ных оператора: t\ ;= b + с t2:=x+y Указанные операторы могут быть переставлены без влияния на значение луча тогда и только тогда, когда Ц отличается от х и у, и t2 отличается от b и с. Следует заметить, что нормальная форма луча позволяет все перестановки операторов, которые явля- ются возможными. Алгебраические преобразования Существует бесконечно много алгебраических преобразований, которые могут ис- пользоваться для замены множества выражений, вычисляемых некоторым лучом, на алгебраически эквивалентное ему множество. Наиболее полезными из них являются те, которые упрощают выражения или заменяют в них дорогие операции на более дешевые. Например, такие операторы, как х :=х + 0 или х :=х * 1 можно удалить из луча без изменения множества выражений, которые он вычисляет. Операция возве- дения в степень в операторе х :=у ** 2 обычно требует вызова функции для своей реализации. Используя алгебраическое преобразование, этот оператор можно заменить на более дешевый эквивалентный х :—у *у. Более подробно алгебраические преобра- зования будут рассмотрены в разд. 9.7, посвященном покадровой оптимизации. 9.3.3. Информация о последующем использовании Использование некоторой переменной в трехадресном операторе определяется сле- дующим образом. Предположим, что трехадресный оператор i присваивает некото- рое значение переменной х. Если х является операндом оператора j и управление мо- жет пройти от оператора i к j вдоль пути, внутри которого не содержится присваива- ний переменной х, то говорят, что оператор / использует значение переменной, вычисленное оператором i, а оператор i информационно влияет на оператор j через переменную х.
664 Часть II. Применение графов и граф-моделей Пусть требуется определить для каждого трехадресного оператора х :=у операция z, какие есть последующие использования внутри луча переменных х. у, z. Алгоритм определения последующих использований осуществляет обратный проход (т. е. проход от конца луча к его началу) по каждому лучу. Нетрудно просканировать поток трехадресных операторов для нахождения всех концов лучей аналогичным образом, как это сделано в алгоритме 9.1. Поскольку процедуры могут иметь произ- вольные побочные эффекты, будем для удобства предполагать, что каждый вызов процедуры начинает новый луч. Имея найденным конец луча, можно пройти от него по лучу к его началу, распозна- вая для каждого (в таблице символов) имени х, имеет ли х последующее использова- ние в луче или нет и является ли х живым на выходе из луча. Если до выполнения данного алгоритма выполнен глобальный потоковый анализ, то уже известно для каждого луча, какие имена являются живыми на его выходе. Если же глобальный анализ не делался, предполагается, что все переменные, не являющиеся временными, живы на выходе луча Если же алгоритмы, генерирующие промежуточный код и осуществляющие его оптимизацию, разрешают определенным временным перемен- ным использоваться не только внутри луча, эти переменные необходимо также счи- тать живыми на выходах из лучей. При этом более хорошим в такой ситуации реше- нием является выделение каким-то образом указанных переменных, чтобы не считать все временные переменные живыми на выходах из лучей. Пусть в процессе просмотра луча с конца достигается некоторый трехадресный опе- ратор х ~у операция z, имеющий номер I Тогда необходимо выполнить следующие действия. 1. Присоединить к оператору i имеющуюся в таблице символов информацию отно- сительно последующих использований и живости переменных х, у и z. 2. В таблице символов приписать переменной х атрибуты "не жива" и "нет после- дующего использования". 3. В таблице символов приписать каждой из переменных у и z атрибуты "жива" и "/ является последующим использованием". Следует заметить, что действия 2 и 3 нельзя поменять местами, поскольку х может совпадать с у или z. В случае, когда оператор i имеет вид х :=у или х операция у, нужно выполнить те же самые действия, просто игнорируя в них z. В оптимизирующем трансляторе может быть полезно создавать отличное от других имя каждый раз, когда возникает потребность во временной переменной, необходимо отводить память для хранения значений этих временных переменных, и размер этой памяти, если не предпринимать специальных мер, растет при увеличении числа вре- менных переменных. В общем случае можно две временные переменные размещать в одном и том же эле- менте памяти, если нет момента исполнения, в котором они живы одновременно. Поскольку почти все временные переменные определяются и используются внутри лучей, информация о последующем использовании может применяться для упаковки
Гпава 9. Кодогенерация 665 временных переменных. Для временных переменных, чье использование распростра- няется за границы лучей, необходимо применять методы глобального потокового анализа (см. разд. 10.5), чтобы определить, какие из них живы на выходах из лучей. Можно распределить память под временные переменные путем последовательной обработки каждой из них и приписывания обрабатываемой временной переменной к первой такой ячейке из области, отведенной под размещение временных перемен- ных, которая в данный момент не содержит живых временных переменных. Если некоторая временная переменная не может быть приписана ни к одной ранее создан- ной ячейке, нужно добавить еще одну ячейку к области, отводимой для распределе- ния для временных переменных текущей процедуры. Во многих случаях временные переменные можно размещать на регистрах, а не в ячейках памяти, как это описыва- ется в следующем разделе. Z, := а * а t\ := а * а t2:= а* Ь h"a*b b,~2* 12 l2-.= l* /2 Ц t\ + 6 z, := z, + z2 z5 := b * Ь z2 := b * b 4 := Ц + 4 t\ -= h + h а) б) Рис. 9.10. Размещение в памяти временных переменных: а — использование шести временных переменных, б— использование двух временных переменных Например, шесть временных лучей, изображенных на рис. 9.10, а, могут быть разме- щены в двух ячейках (см. рис. 9.10, б), которые обозначены через tt и t2. 9.3.4. Управляющие графы и представление лучей Можно добавить к множеству лучей, построенных по программе, информацию о по- токе управления путем конструирования ориентированного графа, называемого управляющим графом (или просто уграфом). Вершинами управляющего графа являются лучи, а дуги, соединяющие вершины, от- ражают возможность передачи управления от одного луча к другому. Если возможно некоторое исполнение программы, при котором луч б2 непосредственно следует за лучом В\, если: П имеется условный или безусловный переход от последнего оператора луча Bt к первому оператору луча В2, □ В2 непосредственно следует за Вх в программе, и В\ не заканчивается безусловным переходом, то в управляющем графе имеется дуга, соединяющая луч Bt с лучом В2. В последнем случае говорят, что В\ является предшественником В и В2 — пре- емником В\.
666 Часть II. Применение графов и граф-моделей Одна вершина уграфа выделена как начальная', обычно ею является тот луч, чей ли- дер — это текстуально первый оператор программы. На рис. 9.11 показан управляющий граф программы, изображенной в листинге 9.4; здесь В\ — начальная вершина. Заметим, что в последнем операторе переход к опе- ратору (3) заменен на эквивалентный переход на начало луча В2. В 1 Рис. 9.11. Управляющий граф Луч в уграфе может быть представлен разнообразными структурами данных. Например, после разбиения трехадресных операторов алгоритмом 9.1 каждый луч может быть представлен записью, состоящей из счетчика, содержащего число четве- рок в луче, из указателя на лидера (первую четверку) и из списков предшественников и преемников луча. Альтернативный подход состоит в создании для каждого луча своего связанного спи- ска четверок. Явные ссылки на номера четверок в операторах переходов, расположенных на кон- цах лучей, могут привести к трудностям, если четверки перемещаются во время оп- тимизации кода. Например, если в промежуточном коде, представленном в листин- ге 9.4, будет перемещен куда-нибудь в массиве четверок луч В2, составленный из операторов с номерами от (3) до (12), ссылка (3) в операторе если i <= 20 на (3) должна будет измениться. Таким образом, в операторах переходов лучше иметь ссылки не на четверки, а на лучи, как это было сделано на рис. 9.10. Важно также заметить, что некоторая дуга управляющего графа от одного луча В к другому В' не специфицирует те условия, при которых происходит переход от В к В'.
Гпава 9. Кодогенерация 667 Эта информация может быть извлечена, когда она необходима, из оператора перехо- да, являющегося последним в луче В Что такое цикл в управляющем графе и как найти все циклы? В большинстве случаев достаточно легко ответить на эти вопросы (см. разд. 4.3.1). Например, на рис. 9.11 имеется один цикл, состоящий из луча В2. Однако в общем случае получение ответа встречает определенные трудности. Вместе с тем, в представленных методах генера- ции достаточно под циклом понимать одновходовую зону (или, что то же самое, од- новходовый нетривиальный сильно связанный подграф) управляющего графа. Цикл, который не содержит других циклов, называется внутренним. 9.4. Простой кодогенератор Рассмотрим стратегию кодогенерации, которая порождала бы объектный код по по- следовательности трехадресных операторов. Она предполагает поочередное рассмот- рение каждого оператора с учетом текущего нахождения каких-либо операндов опе- ратора на регистрах для получения преимуществ от этого факта, если это возможно. 9.4.1. Вводные замечания Для простоты изложения предполагается, что для каждой операции оператора имеет- ся соответствующая ей операция в целевом языке Также предполагается, что вычис- ленные результаты могут находиться на регистрах так долго, как это возможно; они запоминаются только при выполнении одного из двух следующих условий: □ если их регистры необходимы для других вычислений; П непосредственно вслед за обрабатываемым оператором идет вызов процедуры, передача управления или помеченный оператор. Второе условие означает, что все должно быть сохранено непосредственно перед выходом из линейного участка. Причина этого состоит в том, что после выхода из луча можно перейти к нескольким различным лучам или прийти к некоторому кон- кретному лучу, который достижим из ряда других. В каждом из этих случаев невоз- можно (без сбора дополнительной информации) предполагать, что некоторый эле- мент данных, используемый в луче, появится в одном и том же регистре вне зависи- мости от того, как управление достигает этого луча. Таким образом, чтобы избежать возможных ошибок, простой кодогенератор запоми- нает все при переходе через границы лучей или при встрече вызова процедуры. Однако в дальнейшем, при рассмотрении более сложных алгоритмов, будут описаны некоторые способы сохранения определенных данных на регистрах при переходе через границы лучей. Можно получить разумный код для трехадресного оператора а := b + с, если сгенери- ровать единственную команду ADD Rt, R, единичной стоимости, оставляющую ре- зультат а на регистре R,. Указанный код допустим, только если регистр R, содержит переменную Ь, регистр R, содержит переменную с, и переменная b не является живой
668 Часть II. Применение графов и граф-моделей после данного оператора (т. е. текущее значение b не используется после исполнения оператора). Если же регистр R, содержит переменную Ь, но переменная с размещена в ячейке па- мяти (пусть она также обозначена через с), можно сгенерировать последователь- ность, состоящую из одной команды ADD с, R, стоимости 2 или из двух команд MOV с, R, и ADD Rj, R, суммарной стоимости 3, при условии, что b не является впо- следствии живой. Вторая последовательность является более предпочтительной для случая, когда значение переменной с впоследствии используется, поскольку его в дальнейшем можно взять из регистра R,. Необходимо рассмотреть существенно больше случаев, различающихся тем, где переменные b и с в текущий момент разме- щены, а также тем, будет ли текущее значение переменной с впоследствии использо- ваться. Следует также учесть те возможные случаи, когда один или оба операнда b и с являются константами. Количество вариантов, которые необходимо рассмотреть, увеличится также, если предположить, что операция "+" является коммутативной. Таким образом, можно видеть, что кодогенерация включает рассмотрение громадно- го числа случаев и какой из них будет выбран для данного трехадресного оператора, зависит от контекста, в котором он обрабатывается. 9.4.2. Дескрипторы регистров и адресов Алгоритм кодогенерации использует дескрипторы для хранения следа для содержи- мого регистров и адресов переменных (или имен). Регистровый дескриптор хранит след того, что в данный момент в каждом регистре. Эта информация используется, когда необходим новый регистр. Предполагается, что вначале регистровый дескриптор показывает, что все регистры пусты (это не могло быть так, если бы регистры присваивались за границами лучей). В процессе обработ- ки кодогенератором луча каждый регистр в любой заданный момент будет хранить значение нуля, одного или больше переменных. Адресный дескриптор хранит след элемента (или элементов), где текущее значение имени может быть найдено во время исполнения. Этим элементом может быть ре- гистр, элемент стека, адрес памяти или некоторое их множество, поскольку при ко- пировании значение сохраняется в том месте, где оно хранилось ранее. Эта информа- ция может храниться в таблице символов и использоваться для определения метода адресации переменной. 9.4.3. Алгоритм кодогенерации Алгоритм кодогенерации воспринимает на входе последовательность операторов, составляющих луч. Для каждого трехадресного оператора вида х := у операция z выполняются следующие действия. □ Вызывается функция дайрег для определения места L, где результат вычисления выражения у операция z должен быть запомнен. Обычно L является некоторым регистром, но оно также может быть ячейкой памяти (краткое описание функции дайрег приведено в разд. 9.4.4).
Гпава 9. Кодогенерация 669 □ Делается обращение к адресному дескриптору для у, чтобы определить у', теку- щее место у (одно из текущих мест j')- Предпочтение отдается регистру у', если значение у в данный момент находится как в памяти, так и на регистре. Если зна- чение у еще не в £, то генерируется команда MOV у', £, чтобы разместить копию у в L. □ Генерируется команда операция z', L, где z'— текущее место z. Снова отдается предпочтение регистру, а не ячейке памяти, если z находится как там, так и там. Если L — некоторый регистр, изменяется его дескриптор для отражения того, что он содержит значение х, а также удаляется х из всех других регистровых дескрип- торов. □ Если текущие значения у и/или z не имеют последующих использований, не яв- ляются живыми на выходе луча и находятся в регистрах, изменяется регистровый дескриптор для указания того, что после исполнения х := у операция z, эти реги- стры не будут далее содержать^ и/или z соответственно. Если текущий трехадресный оператор имеет унарную операцию, шаги алгоритма аналогичны описанным и поэтому детально здесь не рассматриваются. Важный спе- циальный случай, однако,— это обработка трехадресного оператора х:=у. Если у находится в регистре, нужно просто изменить регистровый и адресный дескрипторы для отражения того, что значение х теперь находится только в регистре, который хранит значение у. Если у не имеет последующего использования и не является жи- вой на выходе из луча, регистр в дальнейшем не хранит значение у. Если у есть только в памяти, можно было бы, в принципе, отмечать, что значение х находится в месте у, но эта опция могла бы усложнить алгоритм, поскольку в этом случае нельзя было бы изменить значение у без сохранения значения х. Таким обра- зом, если у в памяти, алгоритм использует функцию дайрег для нахождения регистра, в который загружается у, и делает этот регистр местом для хранения х. Альтернативно можно генерировать команду MOV у, х, что является предпочтитель- ней для случая, когда значение х не имеет последующего использования в луче. Важ- но заметить также, что во многих, если не во всех, случаях команды копирования будут удалены, если в дальнейшем применить алгоритмы оптимизации. Как только все трехадресные операторы луча будут обработаны, осуществляется за- поминание с помощью команды MOV тех имен, которые живы на выходе и не нахо- дятся в ячейках памяти. При этом используется регистровый дескриптор для опреде- ления, какие имена остались на регистрах, адресный дескриптор для определения того, что то же самое имя еще не находится в ячейке памяти, а также информация о живых переменных для определения того, должно ли быть сохранено указанное имя. Если нет информации о живых переменных, собранной предварительно выпол- ненным потоковым анализом лучей, следует предполагать, что все определенные программистом имена являются живыми на выходе луча. 9.4.4. Функция нахождения места размещения Функция дайрег возвращает место L для выделения под хранения значение х для присваивания х :=у операция z. Многое можно расширить в реализации этой функ-
670 Часть II. Применение графов и граф-моделей ции для того, чтобы осуществлять более правильный выбор L. Рассмотрим неслож- ную для реализации схему, основанную на информации последующего использова- ния (см. разд. 9.3.3). 1. Если имя у находится на регистре L, который не хранит значений других имен (напомним, что обработка операторов копирования вида х := у может приводить к тому, что один регистр одновременно хранит значения двух или более перемен- ных), у не является живой и не имеет последующего использования после выпол- нения х:=у операция z, то возвращается регистр L для у. Изменяется адресный дескриптор для отражения того, что у не находится далее в L. 2. В случае неуспеха в (1) возвращается пустой регистр L, если он есть. 3. В случае неуспеха в (2), если х имеет последующее использование в луче или опе- рация является некоторой операцией, такой как индексирование, которая требует регистр, то выбирается один из занятых регистров R. Запоминается значение R в ячейке памяти (с помощью MOVR, М), если оно еще не находится в подходящей ячейке памяти М, изменяется адресный дескриптор для М и возвращается R. Если R хранит значения нескольких переменных, команда МОУ генерируется для каж- дой переменной, которую надо сохранить. Подходящим занятым регистром мог бы быть один из тех, за чьим значением обращаются в дальнейшем позже всего, или один из тех, чье значение уже находится в памяти. Можно, однако, не уточ- нять способ выбора, поскольку никто еще не доказал, что тот или иной из них яв- ляется наилучшим. 4. Если х не используется в луче или не находится подходящий занятый регистр, вы- бирается некоторая ячейка памяти х в качестве L. Более усложненная функция дайрег могла бы также рассматривать последующие использования х и учитывать коммутативность операции при определении регистра для хранения значения х. Например, оператор присваивания d := (а — Ь) + (а — с) + (а — с) может быть оттранс- лирован в следующую последовательность трехадресных операторов: t= а — Ь и := а— с v := t +• и d:=v + u для которой d является живой на выходе. Алгоритм, учитывающий информацию о последующем использовании, мог бы по этой последовательности сгенерировать последовательность команд, изображенных на рис. 9.12. Здесь показываются также значения регистровых и адресных дескрипторов в процессе генерации кода. В адрес- ном дескрипторе не отражается тот факт, что а, Ь и с всегда находятся в памяти. Так- же предполагается, что t, и и v, будучи временными, не находятся в памяти, если не будет явного запоминания их значений с помощью команды МОУ. Первый вызов функции дайрег возвращает Ro в качестве места, в котором вычисляет- ся I. Поскольку а не находится в Ro, генерируются команды МОУ a, Ro и SUB b, Re. Изменяется также регистровый описатель для указания того, что Ro содержит t.
Гпава 9. Кодогенерация 671 Оператор Генерируемый код Регистровый дескриптор Адресный дескриптор Регистры пусты t.-a-b MOV a, Ru SUB b, Ro /?0 содержит / /в /?0 и := а с MOV a, Rt SUB c, Rt /?() содержит / /?, содержит и / в /?0 и В /?, v := t + и ADD /?], Rq Ro содержит г R, содержит и и в /?, v в R, d:=v + и ADD Rh R{> MOV R^d RB содержит d d в Ra da Ro и в памяти Рис. 9.12. Генерируемый код Процесс кодогенерации продолжается указанным образом до тех пор, пока трехад- ресный оператор d := г + и не будет обработан. Затем происходит генерация команды МОУ Ro, d для сохранения живой переменной d на выходе из луча. Стоимость кода, сгенерированного на рис. 9.12, равна 12. Можно понизить ее до 11 путем генерации команды MOV Ro, R\ непосредственно вслед за первой командой и путем удаления команды MOV a, Rt, однако, чтобы сделать это, необходим несколько более сложный алгоритм кодогенерации. Причина понижения стоимости связана с тем, что дешевле загрузить регистр из регистра, чем из памяти. 9.4.5. Генерация кода для операторов других типов Операции индексирования и работы со ссылками в трехадресных операторах обраба- тываются тем же способом, как и бинарные операции. Таблица на рис 9.13 содержит код, сгенерированный для операторов присваивания вида а := &[/] и я[/] := Ь, содер- жащих индексированную переменную, в предположении, что Ь статически разме- щена. Опера- тор 1 в регистре Ri / в памяти Mi f в стеке Код Цена Код Цена Код Цена а := b[i] MOVb (R,) R ! 2 MOV M,R MOV b {R),R 4 МОУ S,(A), R MOVb(R),R 4 o[z] := b MOV b, а ( R,y 3 MOVM,R MOVb,a(R) 5 МОУ Si (A), R MOVb,a(R) 5 Рис. 9.13. Генерация кода для работы с массивами
672 Часть II. Применение графов и граф-моделей Текущее местоположение i определяет кодовую последовательность. Рассматрива- ются три случая в зависимости от того, находится ли i на регистре R,, является ли / ячейкой памяти М, или находится ли i на стеке с относительным адресом S,, и являет- ся ли И указателем на запись активации для I. Регистр R — это тот регистр, который возвращается при вызове функции дайрег. В случае первого присваивания желатель- но оставлять а на регистре R, если а имеет последующее использование в луче и ре- гистр R является доступным. Во втором присваивании предполагается статическое размещение а. Оператор р в регистре Rp р в памяти Мр р в стеке Код Цена Код Цена Код Цена а := *р МОУ *RP, а 2 MOVMp,R MOV*R,R 3 MOPS,,(A), R MOV*R,R 3 *р '.=п MOV a, *RP 2 МОУМр,Р МОУ a, *R 4 MOV a, R MOV R, *SP(A) 4 Рис. 9.14. Генерация кода для работы с указателями Рис. 9.14 показывает результат генерации для операторов присваивания через указа- тель а:= *р и *р := а. В этом случае он определяется местоположением указателя р. Рассматриваются три случая в зависимости от того, где находится р\ в регистре Rp, в ячейке памяти Мр, на стеке со смещением Sp и А — указатель на запись активации для р. R— это регистр, возвращаемый при вызове функции дайрег. Во втором при- сваивании предполагается, что а размещен статически. 9.4.6. Условные операторы Имеются два типа передач управления на машинном уровне. Один тип — передача управления, если значение указанного регистра удовлетворяет одному из шести условий: отрицательное, нулевое, положительное, неотрицательное, ненулевое и не- положительное. Поэтому в машине трехадресный оператор вида если х < у то на z может быть реализован вычитанием у из х в регистре R и передачей управления на z, если значение регистра R отрицательно. Второй подход, общий для многих машин, использует некоторое множество услов- ных кодов для отражения того, является ли последняя величина, вычисленная или загруженная в регистр, отрицательной, нулевой или положительной. Часто команды сравнения (СМР— в объектной машине, описанной в разд. 9.1) обладают свойством, связанным с установкой условного кода без фактического вычисления величины. Так, например, СМР ху сделает условный код положительным, если х > у, и т. д. Команда условного перехода осуществляет передачу управления, если встретилась операция отношения или Обычно используется команда GJ<=z, которая обозначает "передача управления на z, если условный код является
Гпава 9. Кодогенерация 673 отрицательным или нулевым". Например, если х <у то на г может быть реализована последовательностью из двух команд: СМР х, у и CJ < z Если генерируется код для машины с условными кодами, полезно поддерживать де- скриптор условного кода в процессе генерации кода Этот дескриптор может хранить имя, которое последний раз установило условный код, или пару сравненных имен, если условный код последний раз был установлен таким образом. Поэтому можно реализовать х := у + г если х < 0 на z последовательностью MOV у, Ro ADD v, Ro MOV Ro, x CJ<z, если учитывается, что условный переход определяется по х после ADD v, Ro. 9.5. Распределение и присваивание регистров Команды, имеющие операндами лишь регистры, являются короче и быстрее, чем команды с операндами обращения к памяти. Следовательно, правильное использова- ние регистров весьма важно для генерации хорошего кода. В данном разделе пред- ставлены разнообразные стратегии для решения, какие величины программы должны размешаться в регистрах (распределение регистров) и в каких регистрах каждая ве- личина должна размещаться (присваивание регистров). Один из подходов к распределению и присваиванию регистров состоит в приписыва- нии конкретных величин объектной программе к определенным регистрам. Напри- мер, можно принять решение приписать базовые адреса к одной группе регистров, арифметические вычисления — к другой, верх стека периода исполнения — к неко- торому фиксированному регистру и т. д. 9.5.1. Глобальное распределение регистров Достоинством указанного подхода является упрощение задачи разработки трансля- тора. Его недостатки в том, что, будучи примененным в чистом виде, он использует регистры не эффективно, некоторые регистры совсем могут не использоваться на больших частях кода, хотя в них генерируются не являющиеся необходимыми команды загрузки и запоминания. Тем не менее разумно в большинстве вычисли- тельных средах сохранять ряд регистров для базовых регистров, стековых указателей и тому подобных использований, разрешая компилятору произвольным образом рас- поряжаться оставшимися регистрами 22 Зак 202
674 Часть II. Применение графов и граф-моделей Алгоритм кодогенерации, рассмотренный в разд. 9.4.3, использует регистры для со- хранения значений внутри одного луча. Однако все живые переменные запоминают- ся на выходе каждого луча. Чтобы сэкономить некоторые из этих запоминаний и со- ответствующих загрузок, можно разрешить присваивать регистры часто используе- мым переменным и сохранять содержимое этих регистров за границами лучей, т. е осуществлять распределение глобально. Поскольку программы наибольшее время тратят на выполнение самых внутренних циклов, естественный подход к глобально- му распределению регистров состоит в попытке сохранения некоторой часто исполь- зуемой величины в фиксированном регистре по всему циклу. Предположим, что к данному моменту известна циклическая структура управляюще- го графа и известно, какие величины, вычисленные в луче, используются вовне этого луча (в следующем разделе рассматриваются методы вычисления этой информации). Одна из стратегий глобального распределения регистров связана с приписыванием некоторого фиксированного числа регистров для хранения наиболее активных вели- чин в каждом внутреннем цикле. Отобранные значения могут быть разными для раз- личных циклов. А еще не распределенные регистры могут использоваться для хране- ния величин, локальных по отношению к лучу, как это описано в разд. 9.4. Недостат- ком указанного подхода являете^ то, что выбранное фиксированное число регистров не всегда будет оптимальным для выполнения глобального распределения регистров. Однако этот метод прост для реализации, и использовался в реальных трансляторах, например, в так называемом Фортране Н — оптимизирующем трансляторе с Фортра- на для машин серии ИБМ-360. В языках программирования, подобных языкам Си и Блисс, программист может не- посредственно осуществить некоторые распределения регистров, используя описания регистров для хранения определенных величин в регистрах внутри процедуры. Ра- зумное использование описаний регистров может повысить скорость многих про- грамм, но программисту не следует делать распределение регистров без предвари- тельного профилирования программы. 9.5.2. Счетчики использований Простой метод для определения экономии, которая получается от сохранения пере- менной х в регистре при выполнении цикла L, опирается на то, что в рассмотренной модели машины экономится одна единица стоимости для каждого обращения к пе- ременной х, если х находится в регистре. Однако, если воспользоваться подходом предыдущего раздела к генерации кода для луча, имеется большой шанс, что после вычисления х в луче переменная х будет оставаться в регистре, если имеется после- дующее использование х в луче. Таким образом, нужно рассчитывать на единицу экономии для каждого такого использования переменной х в цикле L, которому не предшествует оператор присваивания х в том же самом луче. Можно сэкономить также две единицы, если избавиться от запоминания х на конце луча. Таким образом, если х занимает регистр, подсчитывается экономия в две единицы для каждого луча L, для которого х жива на выходе и в котором х присвоено значение. К расходам сле- дует отнести то, что, если х является живой на входе заголовка цикла, необходимо загружать переменную х в соответствующий ей регистр сразу перед входом в цикл L.
Гпава 9. Кодогенерация 675 Эта загрузка стоит две единицы. Подобно этому для каждого входного луча В цикла L, в котором х является живой на входе некоторого предшественника В вне L, необ- ходимо запомнить переменную х за две единицы стоимости. Однако в предположе- нии, что цикл повторяется много раз, можно пренебречь этими расходами, поскольку они возникают только один раз при каждом входе в цикл. Таким образом, формула для приближенного подсчета пользы от распределения регистра подх внутри цикла L имеет вид: ^^(использоеатле(рцВ)+2*ж11ва(х,В)), где использование^, В)— число Ле/. раз, когда х используется в В до любого определения х, жива(х, В) есть 1, если х жива на выходе из В и получает значение в В, и жива(х, В) равно 0 в противном случае. Нужно отметить, что эта формула приближенная, поскольку не все лучи в цикле вы- полняются с равной частотой и также поскольку эта формула основана на предполо- жении, что цикл повторяется "много" раз. Для других машин может быть разработана некоторая формула, которая аналогична приведенной, но, возможно, совсем не сов- падающая с ней. В качестве примера рассмотрим луч во внутреннем цикле, изображенном на рис. 9.15, где опущены операторы передачи управления и условного перехода Пред- положим, что регистры Во, В, и В2 распределены для хранения величин по всему циклу. Переменные, которые живы на входе и на выходе каждого луча, на рис. 9.15 для удобства изображены непосредственно сверху и снизу каждого луча соответст- венно. Рис. 9.15. Внутренний цикл
676 Часть II. Применение графов и граф-моделей Рис. 9.16. Ассемблерный код Для вычисления описанной формулы для х = а отметим, что a — жива на выходе из Вь и ей присвоено значение в но она не жива на выходе из Bi, В3 или В4. Таким образом, ^2*жива(а,В)=2 и использованиё(а, Bt) = 0, поскольку а определяется в В\ Bel. до любого использования. Кроме того, использование^, Bi) = использование^, В3) = 1 и использование^, в4) = 0. Таким образом, ^использование(а,В)=2 . Следовательно, Не/. формула для х = а дает значение 4. Это означает, что экономия от выбора а для рас- пределения в регистрах составляет 4 единицы. Соответствующие величины для Ь, с, d, enf равны 6, 3, 6, 4 и 4. Таким образом, можно выбрать а, b и d для регистров Rt„ R\ и Ri соответственно. Использование Ro для е или f вместо а могло бы дать другой вариант распределения с тем же самым доходом. Рис. 9.16 демонстрирует ассемблер- ный код, сгенерированный для фрагмента, изображенного на рис. 9.15, при предпо- ложении, что стратегия, описанная в разд. 9.4, используется для генерации кода для каждого луча. Здесь отсутствует код, который будет порождаться для опущенных операторов условных и безусловных передач управления, которые находятся в конце каждого луча на рис. 9.15, и поэтому сгенерированный код не представлен как еди-
Гпава 9. Кодогенерация 677 ный поток, каким бы он мог получиться на практике. Не лишне заметить, что, если не строго придерживаться рассмотренной стратегии резервирования Ro, Rt и R2, можно использовать SUB R2, Ro MOVR0,f для луча В2, экономя одну единицу, поскольку а не является живой на выходе из В2. Подобная экономия могла бы быть также осуществлена для луча В2. 9.5.3. Присваивание регистров для внешних циклов Имея распределенные регистры и сгенерированный код для внутренних циклов, можно применить тот же самый подход ко все более объемлющим циклам. Если не- который внешний цикл L\ содержит внутренний цикл Ь2, имена, размещенные в ре- гистрах в Ь2, не нуждаются в размещении в £,\ Ь2. Однако, если имя х занимает неко- торый регистр в цикле но не в Ь2, необходимо сохранять х в памяти на входе в L2 и загружать х в регистр, если происходит выход из Ь2 и вход в Lt\ L2. Подобно этому, если выбирается переменная х для размещения в некотором регистре в L2, но не в Lt, необходимо загружать х на входе в Ь2 и сохранять х на выходе из Ь2. 9.5.4. Распределение регистров путем раскраски графа Когда некоторый регистр необходим для вычисления, но все доступные регистры уже использованы, содержимое одного из использованных регистров должно быть запомнено в ячейке (выгружено в ячейку) памяти для того, чтобы освободить ре- гистр. Раскраска графа является простым систематическим методом для распределе- ния регистров и управления выгрузкой регистров. Этот метод предполагает два просмотра. При первом просмотре команды объектной машины выбираются, как если бы имелось бесконечное число виртуальных регист- ров; в результате имена, использованные в промежуточном коде, становятся именами регистров, а трехадресные операторы становятся командами машинного языка. Если доступ к переменным требует команд, которые используют указатели стека, указате- ли дисплея, базовые регистры или другие величины, которые поддерживают доступ, то предполагается, что эти величины хранятся в регистрах, зарезервированных для соответствующих целей. Обычно их использование непосредственно переводится в некоторые виды доступа для адресов, упомянутых в некоторой машинной команде. Если доступ оказывается более сложным, указанный доступ разбивается на ряд ма- шинных команд, и может возникнуть необходимость в создании некоторого времен- ного виртуального регистра (или нескольких регистров). После того как команды построены, второй просмотр приписывает физические реги- стры виртуальным. Цель— нахождение некоторого такого присваивания, которое минимизирует разгрузки.
678 Часть II. Применение графов и граф-моделей На втором просмотре для каждой процедуры конструируется граф несовместимо- стей регистров, вершинами которого являются виртуальные регистры, а каждое ребро, соединяющее два регистра, отражает тот факт, что существует такая точка программы, в которой один из регистров жив, а другой определяется. Например, граф несовместимостей регистров для фрагмента, изображенного на рис. 9 15, содержит в качестве вершин имена а и d. В луче Вх переменная а жива во втором операторе, который определяет </; следовательно, в графе есть ребро между а и d. После построения граф несовместимостей регистров делается попытка раскрасить его в к цветов, где к— число доступных регистров. (Говорят, что некоторый граф раскрашен, если каждой его вершине приписан цвет таким образом, что нет двух смежных вершин, которые получили бы один и тот же цвет ) Каждая краска пред- ставляет отдельный регистр, а существование раскраски гарантирует, что при таком распределении, что одинаково окрашенные виртуальные регистры сопоставляются одному и тому же физическому регистру, между регистрами не возникает несовмес- тимостей. Хотя проблема определения, является ли граф А-раскрашиваемым, в общем случае относится к Л'Г-полным задачам, следующий эвристический метод может обычно использоваться для быстрого осуществления раскраски на практике. Предположим, что некоторая вершина п в графе G имеет менее к смежных (соединенных ребром с и) вершин. Удалим из G вершину п вместе с инцидентными ей ребрами, и получим не- который граф G'. Произвольная А-раскраска графа G' может быть расширена до А-раскраски графа G путем приписывания вершине п того цвета, который не исполь- зован для окраски вершин, смежных с п. Последовательное удаление из графа тех вершин, которые имеют меньше А исходя- щих из них ребер, приведет либо к пустому графу, и тогда нужная А-раскраска для исходного графа легко получается раскраской его вершин в порядке, обратном по- рядку их удаления, либо к графу, в котором у каждой вершины не менее А смежных вершин. В последнем случае некоторая вершина разгружается путем введения кода для запоминания и перезагрузки указанного регистра. Затем граф зацепленностей подходящим образом модифицируется, и процесс раскраски возобновляется. Можно предположить определенные стратегии для выбора вершины для разгрузки. Общее правило— избегать введения кода разгрузки во внутренних циклах. 9.6. Представление лучей дэгами и генерация кода по дэгу Бесконтурные ориентированные графы (или дэги) являются весьма удобными струк- турами данных для реализации преобразований лучей. Дэг луча дает явную картину того, как значение, вычисленное каждым оператором луча, в дальнейшем использу- ется другими операторами луча. Построение дэга по трехадресным операторам явля- ется хорошим способом определения общих подвыражений (т. е. подвыражений, вы- числяемых более одного раза) в луче, определения, какие из переменных использу- ются внутри луча, но вычисляются вне его, а также определения, какие из операторов луча могли бы вычислять переменные для их использования вне луча.
Гпава 9. Кодогенерации 679 9.6.1. Представление линейных участков в виде дэгов Дэг луча (или просто дэг) — это ориентированный бесконтурный граф со следующи- ми пометками на его вершинах: 1. Листья помечены отдельными идентификаторами: либо именами переменных, ли- бо константами. По операциям, примененным к именам, можно определить, необ- ходимо их /-значение или r-значение, т. е. используется ли переменная как адрес или как значение; большинство листьев изображают r-значения. Листья представ- ляют начальные значения имен, и им иногда будет приписываться индекс 0, чтобы предотвратить возможные коллизии с метками, обозначающими "текущие" значе- ния имен. 2. Внутренние вершины помечены символами операций. 3. Вершинам также может быть приписана последовательность идентификаторов в качестве меток. Смысл такого приписывания состоит в том, что внутренние вер- шины изображают вычисленные значения, и те идентификаторы, которые поме- чают некоторую вершину, должны получать это значение. В листинге 9.5 пред- ставлен трехадресный код, соответствующий лучу В7, изображенному в листин- ге 9.4. Для удобства операторы пронумерованы, начиная с единицы. Соответствующий дэг показан на рис. 9.17. ( Листинг 9.5. Трехадресный код луча (1) ti:=4*/ (2) fe := а[б] (3) t3 := 4 * / (4) U := b [fe] (5) fs := * U (6) fe := x + te (7) x := /6 (8) f7:=/ + 1 (9) i := t7 (10) если / <= 20 на (1) Следует заметить, что каждая вершина дэга представляет некоторую формулу, выра- жающую значение в терминах операций над листьями, т. е. над значениями, которы- ми обладают переменные или константы на входе в луч. Например, вершина, поме- ченная символом /4 на рис. 9.17 представляет формулу b[4 * z], т. е. то значение ячей- ки, адресуемой смешением 4 * i от адреса Ь, которое предназначено для /4. 9.6.2. Конструирование дэга луча Для построения дэга по лучу происходит поочередная обработка каждого его опе- ратора в порядке их вхождения в луч. Когда встречается оператор вида х := у + z,
680 Часть II Применение графов и граф-моделей сначала находятся вершины, изображающие "текущие" значения у и о. Они могут быть листьями либо внутренними вершинами дэга, если у и/или z вычислялись пре- дыдущими операторами луча. Затем создается вершина, помеченная символом "+", с двумя сыновьями (левый сын— вершина для у, а правый— вершина для z), и ей приписывается метка х. Однако, если уже существует в дэге вершина, обозначающая то же значение, как и у + z, нет нужды добавлять новую вершину в дэг, а следует просто существующей вершине в качестве дополнительной метки приписать пере- менную х. При этом необходимо учесть следующее Во-первых, если переменная х (но не х0) помечает некоторую другую вершину, нужно удалить эту метку, поскольку "теку- щим" значением х является только что созданная вершина. Во-вторых, для некоторых присваиваний, таких как х:=у, нет нужды создавать новую вершину, а достаточно добавить метку х к списку имен вершины, которая представляет "текущее" значе- ние у. Приведем алгоритм для вычисления дэга по лучу. Следует иметь в виду, что алго- ритм может работать некорректно, если есть присваивания массивам, неявные при- сваивания через указатель или возможность ссылаться нескольким именам на одну и ту же ячейку памяти (что возникает из-за оператора эквивалентности или подстанов- ки параметров). Рассмотрим необходимые модификации алгоритма для учета данных возможностей. Алгоритм 9.3. Построение дэга Дано. Линейный участок. Объекты и операции. Предполагается существование подходящих структур данных для создания вершин с одним или двумя сыновьями и с определенным разли- чием между "левым” и "правым" сыновьями. Также предполагается наличие в струк- туре места для меток вершин и средств для создания связанного списка приписанных идентификаторов для каждой вершины. Кроме того, предполагается наличие средств, позволяющих поддерживать множество всех идентификаторов (включая константы), для которых имеются ассоциированные с ними вершины в дэге; при этом ассоциированной вершиной является либо лист,
Гпава 9. Кодогенерация 681 помеченный этим идентификатором, либо некоторая внутренняя вершина, список приписанных идентификаторов которой содержит данный идентификатор Предпо- лагается существование функции имя (идентификатор), которая в процессе по- строения дэга выдает последнюю созданную вершину, ассоциированную с иденти- фикатором. Содержательно это— вершина дэга, представляющая то значение, ко- торое имеет идентификатор в данный момент процесса построения дэга. При практической реализации некоторое поле в записи для идентификатора в таблице символов могло бы хранить значение, выдаваемое функцией вершина (идентифи- катор). Требуется. Дэг для данного линейного участка, содержащий следующую информацию: П некоторую метку для каждой вершины. Для листьев меткой является идентифи- катор (допускается также константа), а для внутренних вершин — символ опера- ции; □ для каждой вершины некоторый (возможно пустой) список приписанных иденти- фикаторов (отметим, что среди элементов этого списка нет констант). Метод. Процесс конструирования дэга состоит в последовательном применении к каждому оператору луча следующих действий. Вначале, до обработки первого опе- ратора луча, предполагается отсутствие вершин в дэге и неопределенное значение функции вершина для всех аргументов. В процессе конструирования различаются следующие три случая в зависимости от вида "текущего" трехадресного оператора: (/) х := у операция z, (z7) х := операция у, (iii)x:~y; при этом операция отношения вида если i < =20 на рассматривается как частный случай (/) при неопределенном х. I. Если вершина(у) не определена, создать лист, помеченный символом у, и пусть вершина(у) будет этой вершиной. В случае (/), если вершин a(z) не определена, соз- дать лист, помеченный символом z, и пусть вершина(г) будет этой вершиной. 2. В случае (/) определить, есть ли вершина, помеченная символом операция, чей ле- вый сын— веригина(у), а правый сын — eepuiuua(z). (Эта проверка позволяет не упустить общие подвыражения.) Если ее нет, создать такую вершину. Пусть п обозначает данную найденную или созданную вершину. В случае (/7) определить, есть ли вершина, помеченная символом операция, чей единственный сын— вер- шина(у). Если ее нет, создать такую вершину; и пусть п обозначает указанную найденную или созданную вершину. В случае (/77) пусть п есть вершина(у). 3. Удалить х из списка присоединенных идентификаторов для вершина(х). Добавить х к списку присоединенных идентификаторов для вершины п, найденной на шаге (2), и установить п в качестве вершина(х). Рассмотрим луч в листинге 9.5 и процесс конструирования для данного луча такого дэга, который изображен на рис. 9.17. Первым обрабатывается оператор Ц := 4*/. Сна- чала создаются листья, помеченные 4 и /0 (здесь используется индекс 0, как и раньше,
682 Часть II. Применение графов и граф-моделей раньше, для того чтобы различать приписанные идентификаторы на рисунках, но индекс не является реальной частью метки). Затем создается вершина, помеченная символом *, и в конце обработки оператора к ней приписывается идентификатор t\. Рис. 9.18,я показывает вид дэга в этот момент. Для второго оператора, t2 := о[б], создается новый лист, помеченный о, и находится ранее созданная вершина, являющаяся значением вершина!^). Также создается новая вершина, помеченная операцией доступа к элементу массива [], к которой в качестве сыновей присоединяются вершины, созданные для а и Для третьего оператора /3 := 4 ♦ I определится, что вершнна(4) и вершин а(Г) уже суще- ствуют. Поскольку операция * уже есть, нет необходимости создавать новую верши- ну, а просто происходит присоединение t3 к списку идентификаторов, сопоставлен- ных вершине для Ц. Результирующий дэг показан на рис. 9.18, б. Рис. 9.18. Конструируемый дэг. а— после завершения обработки первого оператора, б — в момент завершения обработки третьего оператора Процесс продолжается аналогичным образом. Рассмотрим еще шаг обработки девя- того оператора i := Z7. Перед этим шагом вершинф!) является листом, который поме- чен символом /о- Данный оператор— частный случай (»7); следовательно, при его обработке сначала находится вершин а(1-ф затем присоединяется z к ее списку иден- тификаторов, и наконец устанавливается вершинa(j) на вершина^). Оператор (9) яв- ляется одним из двух операторов луча (другим является оператор (7)), для которых значение вершина изменяется на идентификатор. Это изменение гарантирует, что новая вершина для I является левым сыном вершины для операции <=, которая кон- струируется для десятого оператора. 9.6.3. Применение дэгов Можно указать несколько видов полезной информации, которую легко можно со- брать во время выполнения алгоритма 9.3. Во-первых, автоматически обнаружива- ются общие подвыражения. Во-вторых, можно определить, у каких идентификаторов значения используются в луче; это в точности те идентификаторы, для которых в некоторый момент создается лист. В-третьих, можно определить, какие операторы вычисляют значения, которые могли бы использоваться вне луча. Это в точности все те операторы S, что вершина п, соответствующая S, конструируется или находится в процессе обработки оператора, причем вершина(х) = п в конце процесса конструиро-
Гпава 9. Кодогенерация 683 вания дэга, где х— переменная, которой присваивает значение оператор S (эквива- лентно, х еще является приписанным идентификатором для и). В примере из разд. 9.6.2 при обработке любого оператора только тогда вершина пе- реопределяется (для х и /), когда предыдущим значением вершина был лист. Таким образом, значения у всех внутренних вершин могут использоваться вне луча. Теперь предположим, что перед оператором (9) имеется некоторый новый оператор S, который присваивает значение /. При обработке оператора S была бы создана вер- шина т и установлена вершина!/) = т. Однако при обработке оператора (9) значение вершина(!) переопределилось бы. Таким образом, величина, вычисленная оператором S, не может использоваться вне луча. Другим важным видом использованием дэга является реконструирование более про- стого списка четверок с получением преимуществ от выявленных общих подвыраже- ний и от отсутствия тех пересылок (или присваиваний видах :=у), без которых мож- но обойтись. Порождаются лишь те пересылки, которые абсолютно необходимы. Это означает, что, когда в списке, приписанном вершине, содержится больше одного идентификатора, проверяется, какой из этих идентификаторов, если такой есть, ну- жен вне луча. Как уже отмечалось, для нахождения живых переменных на выходах лучей требуется глобальный потоковый анализ (анализ "живых" переменных), рас- смотренный в разд. 10.5. Однако во многих случаях можно предполагать, что нет временных имен, таких как г1; t2,... /7 в листинге 9.5, необходимых вне луча (но нуж- но учесть, как осуществляется трансляция логических выражений, поскольку при трансляции одного логического выражения может получаться несколько лучей). В общем случае можно вычислять внутренние вершины дэга в любом порядке, кото- рый топологически сортирует дэг. В топологической сортировке некоторая вершина не вычисляется до тех пор, пока не вычислятся все ее сыновья, которые являются внутренними вершинами. Когда вычисляется некоторая вершина, ее значение при- сваивается одной переменной х из списка приписанных ей идентификаторов, пред- почтительно такой, чье значение необходимо вне луча. Однако выбор переменной х будет невозможен, еслй имеется другая вершина т, чье значение также хранится в х, и такая, что т уже вычислена и еще "жива". Здесь, вершина т называется живой, ес- ли ее значение нужно вне луча или если т имеет родителя, который еще не был вы- числен. Если у вершины п имеется в списке приписанных переменных несколько идентифи- катов yi, у2, ..., Ук, чьи значения нужны вне луча, строятся операторы yt := х, у2 := х,..., ук := х. Если п совсем не имеет приписанных идентификаторов (это могло бы слу- читься, если, скажем, и была создана некоторым присваиванием х, но х в дальнейшем переприсваивается), создается некоторое новое временное имя для хранения значе- ния п. Следует иметь в виду, что при наличии присваиваний через указатель или эле- ментам массива не всякая топологическая сортировка дэга является допустимой (см. разд. 9.6.4). Рассмотрим реконструкцию луча по дэгу, изображенному на рис. 9.17, упорядочивая вершины в том же самом порядке, как они были созданы: ц, t2,1$, t$, t(„ t2, (1). Заме- тим, что операторы (3) и (7) исходного луча (см. листинг 9.5) не создают новых вер-
684 Часть II. Применение графов и граф-моделей шин, но добавляют метки /3 и х к списку идентификаторов вершин и t6 соответст- венно. Предполагается, что ни одна из временных переменных t, не нужна вне луча. Процесс начинается с вершины, представляющей 4 * /. Эта вершина имеет два при- писанных идентификатора и t3. Пусть выбран для хранения значения 4 * z, так что конструируется тот же оператор := 4 * z, какой был в исходном луче. Второй рас- сматриваемой является вершина, помеченная /2. Оператор, который конструируется по этой вершине, является 1г'= а[/|], т. е. тот же, что и раньше. Следующей рассмат- риваемой является вершина, помеченная £>, по которой генерируется оператор /4 := Последний оператор использует в качестве аргумента Ц, а не /3, как это бы- ло в исходном луче, поскольку 1\ является именем, выбранном для величины 4 * z. Затем рассматривается вершина, помеченная /5, и генерируется оператор /5 := ?2 * ti- Для вершины, помеченной списком /6, х, выбирается х для хранения соответствующе- го значения, поскольку х, а не /6 будет (вероятно) нужен вне луча. Подобно /3 времен- ная переменная t6 исчезает. Следующим генерируется оператор х :=х + /5. Аналогич- но предыдущему случаю выбирается z, а не /7 для хранения величины z + 1. Послед- ними двумя генерируемыми операторами являются z := z + 1 если z < = 20 то (1). Нужно заметить, что использование выявленных общих подвыражений в процессе конструирования дэга и отказ от порождения пересылок, не являющихся необходи- мыми, позволил уменьшить число операторов луча с десяти до семи. 9.6.4. Массивы, указатели и вызовы функций Рассмотрим линейный участок х := а[/] «[/] -=У z = «['] Если использовать алгоритм 9.3 для конструирования дэга по этому лучу, a[z] могло бы быть выявлено в качестве общего подвыражения, и "соптимизированный" луч мог бы принять вид х := a[i] z :—х «[/] ~У- Вместе с тем, эти два луча вычисляют различные значения для z в случае, когда i =j и у Ф а[1]. Дело состоит в том, что, когда происходит присваивание массиву а, может измениться r-значение выражения а[1], даже если а и z не изменяются. Поэтому при обработке присваивания массиву а необходимо убивать все те вершины, помечен- ные [ ], чей левый аргумент— это а плюс или минус некоторая константа (возможно нуль). Это означает, что вершины должны попадать в разряд вершин, не имеющих права на получение дополнительных идентификаторов в качестве меток, что препят-
Гпава 9. Кодогенерация 685 ствует ложному распознаванию их в качестве общих подвыражений. Для реализации этого каждой вершине сопоставляется битовый атрибут, который хранит информа- цию о том, убита вершина или нет. Далее, для каждого массива, упомянутого в луче, удобно иметь список всех вершин, которые еще не убиты, но должны быть убиты в случае присваивания некоторому элементу массива a Подобная проблема возникает, если возможны присваивания вида *р:= w, где р явля- ется указателем. Если не известно, на какие переменные не может в данной точке программы ссылаться р, всякая построенная к данному моменту вершина дэга долж- на быть убита в указанном смысле. Если вершина п, помеченная а, убивается и име- ется последующее присваивание а, необходимо создать новый лист для а и использо- вать этот лист, а не и. Рассмотрим ограничения на порядок вычислений, вызванные убиванием вершин. Существуют методы, позволяющие сузить подмножество тех переменных, на кото- рые может ссылаться тот или иной указатель р. Если известно, что указатель р может ссылаться лишь на г или s, то только вершина(г) и веришна($) должны быть убиты. Если доступна (или выявлена) информация о том, что равенство i =j не возможно в обрабатываемом луче, то оператор 4z[/] :=у не является причиной убивания вершины для а[/]. Однако нужно заметить, что эффект от использования последнего вида ин- формации обычно не стоит тех затрат, которые нужно затратить на ее извлечение. Вызов процедуры в луче убивает все вершины, поскольку при отсутствии информа- ции о вызываемой процедуре необходимо предполагать, что ее побочным эффектом является перевычисление любой переменной. Следует, однако, отметить, что суще- ствуют методы, позволяющие осуществлять приближенный анализ побочных эф- фектов. Если есть желание реконструировать по дэгу луч, не следуя тому порядоку, в кото- ром созданы вершины дэга, нужно указывать в дэге, что определенные внешне неза- висимые вершины должны вычисляться в некотором определенном порядке. Напри- мер, в рассмотренном выше луче оператор z := а[7] должен следовать за оператором с/[/] := у, который должен следовать за оператором х := <z[z]. Поэтому к дэгу можно добавить определенные дуги и —> nt, указывающие не на то, что т— аргумент и, а отражающие тот факт, что вычисление п должно следовать за вычислением т при любом вычислении дэга. Правила задания указанных дуг следующие. 1. Любое вычисление, использующее значение элемента массива, должно следовать за предшествующим ему присваиванием некоторому элементу этого массива, если такое есть. 2. Любое присваивание некоторому элементу массива а должно следовать за любым предшествующим ему вычислением а. 3. Любое использование любой переменной должно следовать за предшествующим ему вызовом процедуры или косвенным присваиванием через указатель, если оно есть. 4. Любой вызов процедуры или оператор, осуществляющий косвенное присваивание через указатель, должен следовать за всеми предшествующими ему вычислениями любой переменной.
686 Часть II. Применение графов и граф-моделей Это означает, что, когда переупорядочивается код, использования массива не могут менять порядок относительно друг друга и нет операторов, которые могли бы изме- нить порядок расположения по отношению к вызовам процедур и операторам при- сваивания через указатель. 9.6.5. Генерация кода по дэгу Рассмотрим методы генерации кода по представлению линейного участка в виде дэга. Преимуществом такого подхода является упрощение задачи переупорядочения с целью нахождения того порядка, в котором следует осуществлять вычисления, в сравнении со случаем, когда входом кодогенерации является последовательность трехадресных операторов или четырехадресных. Основной случай— это когда дэг является деревом. Для этого случая существует алгоритм, который генерирует код, оптимальный относительно таких критериев, как длина или число используемых рабочих переменных. Указанный алгоритм опти- мальной генерации кода по дереву может также использоваться в том случае, когда промежуточное представление является деревом разбора. 9.6.6. Задача переупорядочения Порядок, в котором осуществляются вычисления, может влиять на стоимость резуль- тирующего объектного кода. Пусть имеется следующий линейный участок: (1)Й := а + b (2) fc := с + d (3) fe :=e-fe (4) f4 := й - fe представление которого в виде дэга является деревом, изображенным на рис. 9.19. Рис. 9.19. Дэг луча Если генерировать код в виде трехадресных команд, пользуясь алгоритмом, описан- ным в разд. 9.6.10, можно получить результирующий код, представленный в листин- ге 9.6, предполагая, что доступно два регистра 7?0 и 7?1 и только переменная /4 жива на выходе.
Гпава 9. Кодогенерация 687 Листинг 9.6. Сгенерированный код для исходного луча (1) MOV a, Ro (2) ADD b, Ro (3) MOV c, R, (4) ADD d, Ri (5) MOV Ro, ti (6) MOV e, Ro (7) SUB Rb Ro (8) MOVh, Ri (9) SUB Ro, Ri (10) MOVRi,t« С другой стороны, предположим, что до генерации произведено переупорядочение последовательности операторов таким образом, чтобы вычисление Ц происходило бы непосредственно перед /4: tz := с + d t3 := е -12 ti ~ а + b tj =ti- t3. Тогда, используя тот же алгоритм (см. разд. 9.6.10), можно получить код, представ- ленный в листинге 9.7, снова предполагая, что только 7?0 и доступны. При выпол- нении вычислений в указанной последовательности можно сэкономить две команды: команду MOV Ro, lt, которая запоминает значение /?0 в ячейку th и команду MOVtu Ri, которая перезагружает значение /| в регистр /?1. Листинг 9.7. Сгенерированный после переупорядочения операторов код ADD d, Ro MOV e, R-i SUB Ro, Ri MOV a, Ro ADD b, Ro SUB R4, Ro MOV Ro, tA 9.6.7. Эвристическое упорядочение для дэгов Причина, по которой описанное переупорядочение улучшило код, состояла в том, что вычисление /4 было осуществлено непосредственно вслед за вычислением ц, его левого операнда в дереве. При выборе упорядочения вершин дэга единственным ограничением является требо- вание, чтобы порядок сохранял отношения, представленные дугами дэга. В листин-
688 Часть II. Применение графов и граф-моделей ге 9.8, приводится алгоритм эвристического упорядочения, который ориентирован на построение такого упорядочения, при котором везде, где это удается сделать, вычис- ление, связанное с некоторой вершиной, непосредственно следовало бы за вычисле- нием его самого левого аргумента. Алгоритм строит упорядочение в обратном по- рядке. i Листинг 9.8. Алгоритм эвристического упорядочения 1. пока есть не включенные в список внутренние вершины цикл 2. Выбрать некоторую не включенную в список вершину п, все предшественники которой уже включены в список; 3. Включить п в список; 4. пока первый преемник m вершины п не имеет не включенных в список предшественников и не является листом 5 цикл Включить m в список; п := m все все Алгоритм при его применении к дереву, изображенному на рис. 9.19, порождает по- следовательность операторов, из которой получается код, представленный в листин- ге 9.7. Для более представительного примера можно рассмотреть применение алго- ритма к дэгу, изображенному на рис. 9.28. Рис. 9.20. Дэг луча Сначала только вершина 1 не имеет предшественников, не включенных в список, так что устанавливается и = 1 оператором 2, и вершина 1 включается в список операто- ром 3. Теперь только левый аргумент вершины 1, т. е. вершина 2, имеет своих пред- шественников в списке, так что вершина 2 включается в список и устанавливается п = 2 оператором 6. Затем оператор 4 находит первого преемника 6 вершины 2, кото- рый имеет не включенного в список предшественника 5. Таким образом, выбирается новое и оператором 2, и только вершина 3 является здесь кандидатом. Вершина 3 включается в список, а затем процесс продолжается переходами вниз, к первому пре-
Гпава 9. Кодогенерация 689 емнику, и включением в список последовательно вершин 4, 5 и 6. После этого среди внутренних необработанных вершин остается только вершина 8, и она включается в список. Получается последовательность 1234568, так что предлагаемый порядок вычислений есть 8654321. Это упорядочение соответствует следующей последова- тельности операторов: te := d + е te := а + b k := te-с ti := ts * fe ts := te + ti := fe * ts Указанная последовательность приводит к более оптимальному коду для дэга по числу регистров, если воспользоваться алгоритмом генерации кода, описанным в разд. 9.4. Следует отметить, что хотя в рассмотренном примере выбор в операто- ре 2 происходит однозначно, в общем случае это не так, и вариантов может быть много. 9.6.8. Оптимальное упорядочение деревьев Можно предложить простой алгоритм определения оптимального порядка, в котором следует вычислять операторы в линейном участке, когда графовое представление луча является деревом. Оптимальность понимается в том смысле, что получаемая последовательность инструкций является самой короткой из всех последовательно- стей, возможных для данного дерева. Этот алгоритм, соответствующим образом мо- дифицированный для учета пар регистров и другой специфики объектной ЭВМ, ис- пользовался в ряде трансляторов с языков Алгол, Блисс и Си. Алгоритм состоит из двух частей. Первая часть помечает каждую вершину дерева, двигаясь снизу вверх, некоторым числом, которое обозначает минимальное количе- ство регистров, необходимое для вычисления поддерева с данным корнем при усло- вии, что не делается запоминаний промежуточных результатов. Вторая часть — это обход дерева, порядок которого управляется вычисленными метками вершин. Вы- ходной код генерируется во время указанного обхода дерева. Идея алгоритма состоит в том, что, обрабатывая два операнда бинарной операции, он сначала работает над организацией вычислений того из них, который требует больше регистров (является более трудным операндом). Если потребность в регистрах у обо- их операндов совпадает, то каждый из операндов может быть обработан первым. 9.6.9. Алгоритм разметки Термин "левый лист" используется для обозначения любой такой вершины, которая является листом и первым преемником своего отца. При этом другие листья будут называться "правыми листьями". Процесс разметки может быть осуществлен при обходе вершин в таком порядке сни- зу вверх, чтобы ни одна вершина не посещалась до тех пор, пока все ее сыновья не
690 Часть II. Применение графов и граф-моделей получат метки Тот порядок, в котором создаются вершины дерева разбора, является подходящим для этого процесса, если дерево разбора используется в качестве про- межуточного представления; так что в этом случае метки можно вычислять в процес- се синтаксически ориентированной трансляции. В листинге 9.9 указан алгоритм для вычисления метки вершины и. В важном частном случае, когда п является бинарной вершиной и ее сыновья имеют метки 1Х и /2, указанная формула оператора 6 редуци- руется к следующему правилу: {тах(/,), если I. /,+1, если /j=/2 Рассмотрим дерево, изображенное на рис. 9.19. Постфиксный обход данного дерева связан с посещением его вершин в последовательности abi\ecdt2t3tn. Постфиксный обход всегда порождает обход, позволяющий осуществлять вычисление меток. Вер- шина а помечается 1, поскольку она является левым сыном. Вершина Ь получает метку 0, поскольку она— правый лист. Вершина /| помечается 1, поскольку метки ее сыновей не равны и 1 — максимальная метка сыновей. Рис. 9.21 показывает полу- ченное в результате помеченное дерево. Видно, что два регистра необходимы для вычисления /4, и два же регистра необходимы для вычисления t3. Листинг 9.9. Алгоритм разметки 1. если п является листом то 2. если п является левым сыром своего отца то меткаф) := 1 3 иначе меткаф) := О все 4. иначе % п — внутренняя вершина % 5. Пусть n-i, г>2, .... Пк— все сыновья вершины п, упорядоченные по их меткам так, что метка ф-t) 2 метка (пг) S ... > метка фк)', 6 меткаф) = max,.,<*(метка(п,) + / - 1) все Рис. 9.21. Помеченное дерево
Гпава 9. Кодогенерация 691 9.6.10. Генерация кода по помеченному дереву Приведем алгоритм, вход которого помеченное дерево Т, а выход — последователь- ность машинных команд, вычисляющих значение Т в регистре Ro (содержимое Ro затем может быть запомнено в подходящем элементе памяти). При этом предполага- ется, что Т содержит только бинарные операции. Обобщение алгоритма на случай, когда операции могут быть произвольной арности, не представляется сложным. Алгоритм реализуется через применение рекурсивной процедуры ГЕНКОД(и) для порождения машинного кода, вычисляющего поддерево Т с корнем и в некотором регистре (листинг 9.10). Процедура ГЕНКОД использует стек рстек для распределе- ния регистров. Сначала, при первом вызове процедуры, рстек содержит все доступ- ные регистры, которые обозначаются через Ro, R\,..., Rr.\, в указанной последова- тельности. Последующие вызовы процедуры ГЕНКОД могут находить некоторое подмножество регистров (возможно, в другой последовательности) на стеке рстек. Когда происходит возврат из ГЕНКОД, регистры на стеке и их упорядочение не из- меняются по отношению к состоянию, которое было в момент вызова. Результирую- щий код вычисляет значение дерева Тв верхнем регистре стека. i Листинг 9.10. Процедура ГЕНКОД проц ГЕНКОД(п) = 1. если (п — левый лист, представляющий операнд имя) л(п — самый левый сын своего отца) 2. то % случай 0 % печать '/WOV|| имя ||','|| э рстек 3. иначе если п — внутренняя вершина с операцией on, левым сыном т и правым сыном п2 4 то если метка (п2) = 0 то % случай 1% 5. Пусть имя является операндом, изображенным вершиной п2; 6. ГЕНКОД(П1); печать ол ||имя||','|| э рстек 7. иначе если (1 < метка(т) < метка(л2)) л (метка(т) < г) то 8. % случай 2 % смена(рстек); ГЕНКОД(л2); R := э рстек, 9. ГЕНКОД(п-|); печать on ||R||’,'|| э рстек, 10. рстек <-R, смена(рстек) 11. иначе если (1 < метка(п2) < метка(т)) л (метка(п?) < г) то 12. % случай 3 % ГЕНКОД(Л1); R := э рстек, 13. ГЕНКОД(л2); печать on ||э рстек||','||R; рстек <- R 14. иначе % случай 4, обе метки не меньше общего числа регистров г % 15. ГЕНКОД(л2); Т := эестек, 16. печать 'МО\/’||э рстек ||','|| Т; ГЕНКОДСлт); 17. естек <- Г; печать on ||Т]|','|| э рстек все все все все все
692 Часть //. Применение графов и граф-моделей Процедура СМЕНА(рсшек) переставляет два верхних регистра, находящиеся на вер- ху стека. Ее использование позволяет гарантировать, что некоторый левый сын и его отец вычисляются в одном и том же регистре. Процедура ГЕНКОД использует стек встек для размещения элементов временной памяти. Предполагается, что он в начальный момент содержит То, Ть Т2,..., Т„. Реально встек не требует реализации в виде списка, если сохранять /, такое, что Т, является текущим верхом стека. Содержимое стека встек всегда является некоторым префиксом То, Тъ Т2,..., Т„. Процедура ГЕНКОД в своей работе различает следующие пять случаев при обработ- ке некоторого дерева Т с корнем и, указанном в качестве параметра. Для случая 0 (см. листинг 9.10) вид обрабатываемого поддерева изображен на рис. 9.22, а. Это означает, что и является самым левым сыном своего отца. Следова- тельно, в этом случае генерируется только инструкция загрузки. Рис. 9.22. Виды обрабатываемого дерева: а — случаи 0, б — случай 1, в — случай 2 В случае 1 (см. линстинг 9.10) обрабатываемое поддерево имеет вид, изображенный на рис. 9.22, б. Поэтому в таком случае процедура ГЕНКОД сначала генерирует код для вычисления щ в регистре А’, находящемся на верху стека рстек, за которым раз- мещает команду операция имя, R. Для случая 2 (см. линстинг 9.10) поддерево имеет вид, изображенный на рис. 9.22, в, и обладает тем свойством, что гц можно вычислить без запоминания, но п2 более трудно для вычисления (т. е. требует больше регистров), чем nt. При обработке этого случая процедура сначала меняет местами два регистра на верху стека рстек, затем генерирует вычисление п2 в регистре R. находящемся на верху стека рстек. Затем R удаляется из стекарстек и генерируется вычисление щ в регистре S, находящемся на верху стека рстек. Заметим, что S — регистр, находящийся на верху стека рстек до начала обработки в данном случае. Затем генерируется команда операция R, S, кото- рая вычисляет значение п (вершины, помеченной символом операция) в регистре S. Еще один вызов процедуры СМЕНА оставляет рстек в том виде, какой он имел до начала вызова процедуры ГЕНКОД. Случай 3 подобен предыдущему случаю с тем отличием, что в нем левое поддерево является более сложным для вычисления и поэтому обрабатывается процедурой пер- вым. Данной случай не обходится без использования процедуры СМЕНА, поскольку перестановка регистров не является необходимой. Случай 4 возникает, когда оба поддерева требуют г или более регистров для вычис- ления без запоминания результатов. Поскольку здесь должны использоваться эле- менты временной памяти, вначале генерируется код для вычисления значения пра-
Гпава 9. Кодогенерация 693 вого поддерева во временной переменной Т, затем левого поддерева, и наконец — корня. В качестве примера, иллюстрирующего работу процедуры ГЕНКОД, можно рассмот- реть процесс генерации кода для помеченного дерева, изображенного на рис. 9.21. Пусть рстек состоит из двух регистров /?0 и Rx. Последовательность вызовов про- цедуры ГЕНКОД и шагов печати кода показано в листинге 9.11. Отдельно, в квад- ратных скобках, представлено содержимое стека рстек в соответствующие моменты вычисления, причем верх стека находится справа. Получаемая последовательность команд представляет собой некоторую перестановку кода, описанного в листинге 9.7. Листинг 9.11. Последовательность вызовов процедуры ГЕНКОД и шагов печати ГЕНКОД(^) [RoRi] ГЕНКОД(/3) [RoRi] ГЕНКОД(е) [RoRi] печать MOIZ е, Ri ГЕНКОД([2) [Ro] ГЕНКОД(С) [Ro] печать MOV с, Ro печать ADD d, Ro печать SUB Rc, Ri ГЕНКОДСМ [Ro] ГЕНКОД(а) [Ro] печать MOV a, Ro печать ADD b, Ro печать SUB Ri Ro % случай 2 % % случай 3 % % случай 0 % % случай 1 % % случай 0 % % случай 1 % % случай 0 % А. Процедура ГЕНКОД генерирует код, который является оптимальным, если не учитываются алгебраические законы операций и общие подвыражения. 9.6.11. Многорегистровые операции Можно модифицировать рассмотренный алгоритм разметки, расширив его на опера- ции (такие как умножение, деление или вызов функции), которые обычно требуют более одного регистра для своего выполнения. Для этого просто нужно изменить оператор 6 алгоритма разметки (см. листинг 9 9) так, чтобы функция метками) всегда вычисляла значение, равное наименьшему числу регистров, необходимых для данной операции. Например, если предполагается, что некоторый вызов функции требует все г регистров, оператор 6 примет вид метка(п) = г. Если же умножение требует двух регистров, то в бинарном случае метка(п) = если Ц А 12 если /| = 12
694 Часть II. Применение графов и граф-моделей К сожалению, указанная модификация не гарантирует, что некоторая пара подряд расположенных регистров будет всегда доступна для некоторого умножения или де- ления или для операций повышенной точности. Полезным приемом для ряда машин является предположение, что умножение или деление требует трех регистров. Если СМЕНА никогда не используется в процедуре ГЕНКОД, то рстек будет всегда со- держать последовательно занумерованные регистры i, i + 1,..., г — 1 для некоторого /. Таким образом, первые три из них уверенно можно включать в пару регистров. Можно получить преимущество от того, что многие операции являются коммутатив- ными, и избавиться от использования случая 2 процедуры ГЕНКОД (см. лис- тинг 9.10), в котором вызывается процедура СМЕНА. Даже если наверху стека рстек не содержится трех подряд расположенных регистров, имеется большой шанс найти пару регистров в самом стеке рстек. 9.6.12. Алгебраические свойства Если допустить использование алгебраических законов для разных операций, появ- ляется возможность попытаться преобразовать исходное дерево Т в другое с мень- шими "величинами в качестве меток (чтобы избавиться от запоминаний в случае 4 процедуры ГЕНКОД) и/или с меньшим числом левых листьев (чтобы избавиться от загрузок в случае 0). Например, поскольку операция "+" обычно считается коммута- тивной, можно перейти от дерева, изображенного на рис. 9.23, а, к дереву рис. 9.23, б, уменьшив тем самым количество левых листьев на единицу и, возможно, уменьшив также значения некоторых меток. а) 6) в) г) Рис. 9.23. Использование алгебраических свойств операций Поскольку операция "+" обычно рассматривается как ассоциативная, а также как коммутативная, можно осуществить преобразование для группы вершин, помечен- ных знаком "+", перейдя от дерева, изображенного на рис. 9.23, в, к дереву на рис. 9.23, г. Для минимизации метки корня необходимо только расставить их так, чтобы было таким поддеревом из 7), 7), Т3 и 7\, которое имеет наибольшую метку.
Гпава 9. Кодогенерация 695 и чтобы 7} не являлось листом, если среди Ть Т2, Т3, есть поддерево, которое не является листом. 9.6.13. Общие подвыражения Когда луч содержит общие подвыражения, соответствующий дэг не будет больше деревом. В нем общие подвыражения будут соответствовать вершинам с более чем одним предшественником, так называемым разделяемым вершинам. К нему нельзя впрямую применить алгоритм разметки и процедуру ГЕНКОД. Общие подвыраже- ния существенно усложняют задачу генерации кода с математической точки зрения. Теорема Бруно— Сети. Задача оптимальной генерации кода по дэгу для одноад- ресной машины является NP-полной. Теорема Ахо — Джонсона — Ульмана. Задача оптимальной генерации кода по дэгу для машины с неограниченным числом регистров является NP-полной. Указанные теоремы показывают сложность задачи определения оптимального по- рядка, в котором вычисляется некоторый заданный дэг самым дешевым способом. На практике можно, однако, получить разумное решение, если разбить дэг на множе- ство деревьев путем нахождения для каждого корня и/или разделяемой вершины п максимальное поддерево сив качестве корня, которое не включает других разделяе- мых вершин, отличных от листьев. При этом каждая разделяемая вершина с р пред- шественниками должна появиться в качестве листа не больше, чем в р деревьях. Вершины с более чем одним предшественником в одном и том же дереве могут быть преобразованы в нужное количество листьев с тем, чтобы получить дерево, в кото- ром нет листьев с многими предшественниками. Когда имеется разбиение дэга на деревья данным способом, можно упорядочить вы- числение деревьев и использовать любой из известных алгоритмов генерации кода для каждого дерева. Этот порядок должен быть таким, чтобы разделяемые значения, которые являются листьями некоторого дерева, были бы доступными, когда дерево вычисляется. Разделяемые величины могут быть вычислены и сохранены в памяти (или сохранены в регистрах, если доступно достаточно регистров). Хотя этот процесс не всегда генерирует оптимальный код, но во многих случаях полученный результат является удовлетворительным. 9.7. Алгоритм кодогенерации, основанный на динамическом программировании Описанная процедура ГЕНКОД производит оптимальный код по дереву выражения за время, линейное относительно размера дерева. Эта процедура применима для слу- чая машин, в которых все вычисления осуществляются на регистрах и в которых команды содержат операции, применяемые к двум регистрам или к регистру и ячейке памяти.
696 Часть II. Применение графов и граф-моделей Чтобы расширить класс машин, для которых оптимальный код может генерироваться по дереву выражения за линейное время, можно использовать алгоритм, основанный на принципе динамического программирования. Алгоритм динамического програм- мирования применим к более широкому классу регистровых машин со сложными системами команд. 9.7.1. Класс регистровых машин Алгоритм динамического программирования может использоваться для генерации ко- да для любой машины с г взаимозаменяемыми регистрами Rn, Rt, ..., Rr , и с команда- ми вида R/ := Е, где Е— выражение, содержащее операции, регистры и ячейки памя- ти. Указанная модель машины покрывает машину, описанную в разд 9.1. Например, команда ADD Ro, Rt могла бы быть реализована в виде R, := /?, + Ro, а команда ADD *R$, R{ в виде Л, := Aj + ind /?0, где ind означает операцию разыменования. Предполагается, что машина имеет команду загрузки R, := Л/, команду запоминания М := R, и операцию пересылки с регистра на регистр R, := Rr Для упрощения изложения предполагается единичная стоимость каждой команды, хотя достаточно очевидная модификация алгоритма динамического программирова- ния позволяет работать с командами, каждая из которых имеет свою собственную стоимость. 9.7.2. Принцип динамического программирования и непрерывное вычисление Алгоритм динамического программирования разбивает проблему генерации опти- мального кода для некоторого выражения на подпроблемы генерации оптимального кода для подвыражений данного выражения. В качестве простого примера рассмот- рим выражение Е вида Et + £2- Оптимальная программа для Е формируется из опти- мальных кодов для Е\ и Е2 путем их комбинирования в том или другом порядке и размещения вслед за ними кода для вычисления операции "+". Проблемы генерации кода для Е| и Е2 решаются аналогично. Оптимальная программа, построенная алгоритмом динамического программирова- ния, имеет важное свойство. Она вычисляет выражение Е = Е\ операция Е2 "непре- рывно". Это можно увидеть на следующем примере синтаксического дерева Т для £, изображенном на рис. 9.24. Здесь Г, и Т2 — деревья для Е\ и Е2 соответственно. Рис. 9.24. Синтаксическое дерево выражения
Глава 9. Кодогенерация 697 9.7.3. Непрерывное вычисление Говорят, что программа Р вычисляет дерево Т непрерывно, если она сначала вычис- ляет те поддеревья Т, которые должны сохранять результат в памяти. Затем она вы- числяет оставшуюся часть Т либо в порядке Тх, Т2 и корень, либо в порядке Т2, Т\ и корень, причем в каждом из двух случаев используя ранее вычисленные значения из памяти, когда они необходимы. Примером вычисления, которое не является непре- рывным, будет такое, которое сначала вычисляет часть Тх, оставляя его значение на регистре (вместо памяти), далее вычисляет Т и затем возвращается к вычислению остатка Т{. Для определенной регистровой машины можно доказать, что, какая бы ни была ма- шинная программа Р для вычисления дерева Т, существует эквивалентная ей про- грамма Р', такая, что: □ Р' не имеет большую стоимость, чем Р\ □ Р' использует не больше регистров, чем Р\ П /"вычисляет указанное дерево непрерывно. Отсюда следует, что каждое дерево можно оптимально вычислить непрерывной про- граммой. Следует заметить, что машины с четно-нечетными регистровыми парами, такие как ЭВМ IBM System/370 не всегда имеют оптимальные непрерывные вычисления. Для такого типа машин существуют примеры деревьев выражений, для которых опти- мальная машинная программа должна сначала вычислить в регистре часть левого поддерева и потом часть правого поддерева, далее вычислить другую часть левого поддерева и затем другую часть правого и т. д. Этот тип колебания не является необ- ходимым для оптимального вычисления любого дерева выражения с использованием общей регистровой машины. Определение непрерывного вычисления говорит о том, что для любого дерева выра- жения Т всегда существует оптимальная программа, которая состоит из оптимальных программ для поддеревьев, за которыми следует команда для вычисления корня. Указанное свойство позволяет использовать алгоритм динамического программиро- вания для генерации оптимальной программы для Т. 9.7.4. Алгоритм динамического программирования Алгоритм динамического программирования работает в три этапа. Предположим, что объектная машина имеет г регистров. На первом этапе вычисляется снизу вверх для каждой вершины и дерева выраже- ния Т массив стоимостей С, в котором z'-й элемент C[z] является оптимальной стои- мостью вычисления в регистре поддерева 5 с корнем и в предположении, что доступ- но i регистров для вычисления, где 1 < i < г. Стоимость включает все загрузки и за- поминания, которые необходимы для вычисления У в имеющемся числе регистров. Она также включает стоимость вычисления операции в корне S. Нулевой элемент вектора стоимостей является оптимальной стоимостью вычисления S в памяти. Свой-
698 Часть II. Применение графов и граф-моделей ство непрерывного вычисления гарантирует, что оптимальная программа для S мо- жет быть сгенерирована при рассмотрении комбинаций оптимальных программ только поддеревьев корня 5. Это ограничение уменьшает число вариантов, которые нуждаются в рассмотрении. Для вычисления C[z] у вершины и рассматривается каждая машинная команда R := Е, чье выражение Е отождествляется с подвыражением с корнем п. Путем просмотра векторов стоимостей соответствующих потомков и определяются стоимости вычис- ления операндов Е. Для тех операндов Е, которые являются регистрами, рассматри- ваются все возможные упорядочения, в которых соответствующие поддеревья Т мо- гут быть вычислены в регистрах. В каждом упорядочении первое поддерево, соответ- ствующее регистровому операнду, может быть вычислено с использованием i доступных регистров, второе — с использованием I — I регистров и т. д. Для подсчета соответствующего значения для и эта величина добавляется к стоимости команды R := Е, которая используется при отождествлении п. Тогда значением С[/] является минимальная стоимость среди всех возможных упорядочений. Векторы стоимостей для всего дерева Т можно вычислить снизу вверх по дереву за время, линейное от числа вершин дерева. Удобно сохранять у каждой вершины той команды, на которой достигается наилучшая стоимость для C[z] для каждого значе- ния I. Минимальная стоимость в векторе для корня Т дает минимальную стоимость вычисления Т. На втором этапе алгоритма осуществляется обход Т с использованием векторов стоимостей для определения, какие поддеревья Т должны быть вычислены в памяти. На третьем этапе делается обход каждого дерева с использованием векторов стоимо- стей и ассоциированных команд для генерации окончательного объектного кода. Код для поддеревьев, вычисленных в ячейках памяти, генерируется первым. Последние два этапа также могут быть реализованы за время, линейно пропорциональное раз- меру дерева выражения. В качестве примера рассмотрим машину, которая имеет два регистра Ro и /?ь а также следующие команды, каждая из которых единичной стоимости: Ri := Ц R, := R, операция R Ri := R: операция Ц Ri := Rj Mi := Rh В этих командах R, является либо Ro, либо Rt, а М, — ячейка памяти. Пусть имеется синтаксическое дерево, изображенное на рис. 9.25. На первом этапе получаются векторы стоимостей, показанные рядом с соответствующими вершина- ми. Можно иллюстрировать это вычисление стоимости на примере вектора стоимо- стей листа а. С[0], стоимость вычисления а в памяти равна 0, поскольку операция всегда там. С[ 1 ], стоимость вычисления а в регистре равна 1, поскольку можно загру- зить переменную в регистр с помощью команды Ro := а С[2], стоимость загрузки а на регистр с двумя доступными регистрами равна той же величине, что и для случая
Гпава 9. Кодогенерация 699 с одним доступным регистром. Следовательно, вектор стоимостей листа а имеет вид (0,1,1). Рис 9.25. Векторы стоимостей вершин синтаксического дерева Рассмотрим вектор стоимостей корня. Сначала определяется минимальная стоимость вычисления корня с одним и двумя доступными регистрами. Машинная инструкция Ro := Ro + М отождествляется с корнем, поскольку корень помечен операцией "+". Используя эту команду, минимальная стоимость вычисления корня с одним доступ- ным регистром является минимальная стоимость вычисления его правого поддерева в памяти плюс минимальная стоимость вычисления его левого поддерева в регистре плюс 1 для указанной команды. Других способов не существует. Вектора стоимостей правого и левого сыновей корня показывают, что минимальная стоимость вычисле- ния корня с одним доступным регистром равна 5 + 2 + 1 = 8. Теперь рассмотрим минимальную стоимость вычисления корня с двумя доступными регистрами. Возможны следующие три случая в зависимости от того, какая команда используется для вычисления корня и в каком порядке левое и правое поддеревья корня вычисляются. 1, Сначала вычисляется в регистре /?0 левое поддерево с двумя доступными регист- рами, затем вычисляется в регистре R-, правое поддерево с одним доступным реги- стром и наконец вычисляется корень с использованием команды /?0 ;= Ro + R\- Указанная последовательность имеет стоимость 2 + 5 + 1 = 8 2. Сначала вычисляется в R\ правое поддерево с двумя доступными регистрами, за- тем вычисляется в Ro левое поддерево с одним доступным регистром и наконец используется команда Ro'.— Ro + Ri- Эта последовательность имеет стоимость 4 + 2+ 1 = 7. 3. Сначала вычисляется в ячейке Л/ правое поддерево, затем вычисляется в Ro ле- вое поддерево с двумя доступными регистрами и наконец используется команда /?о := Ro + М. Стоимость этой последовательности равна 5 + 2 + 1 = 8 Из этих трех случаев второй имеет минимальную стоимость, равную 7. Минимальная стоимость вычисления корня в ячейке памяти равна увеличенной на единицу стоимости вычисления корня со всеми доступными регистрами; т. е. дости-
700 Часть II. Применение графов и граф-моделей гается на последовательности, в которой сначала вычисляется корень в регистре, а затем запоминается результат. Следовательно, вектор стоимостей корня будет иметь вид (8, 8, 7). По векторам стоимостей легко конструируется последовательность кода путем осу- ществления обхода дерева. По дереву на рис. 9.24 в предположении, что два регистра доступно, оптимальной последовательностью кода является: Ro := с Ri :=d R-i := Rile Ro := Ro *Ri Ri := a Ri := Ri - b Ri := R-\ + Ro Указанная методика облегчает перенастройку, поскольку применимость метода ди- намического программирования распространяется на широкий класс машин. 9.8. Покадровая оптимизация Поскольку алгоритмы генерации, как правило, обрабатывают лучи достаточно неза- висимо, результирующий код может содержать "неоптимальности" на "стыках" сге- нерированных последовательностей машинных команд. Для удаления этих (и других порождаемых генератором) неоптимальностей полезно осуществлять покадровую оптимизацию сгенерированного кода. Эта оптимизация, будучи довольно простой по реализации, позволяет в среднем повысить скорость работы сгенерированной про- граммы на 20% и сократить ее длину на 10%. 9.8.1. Понятие покадровой оптимизации Стратегия генерации кода "оператор за оператором" часто порождает объектный код, который содержит избыточные команды и неоптимальные конструкции. Качество такого объектного кода может быть повышено путем применения так называемых оптимизирующих преобразований объектной программы. Термин "оптимизирую- щие" может некоторых ввести в заблуждение, поскольку при этом никак не гаранти- руется, что результирующий код является оптимальным по какому-нибудь критерию качества. Тем не менее есть много простых преобразований, применение которых может заметно улучшить время исполнения и потребность в памяти объектной про- граммы, так что важно знать, какие виды оптимизирующих преобразований полезны на практике. Простым, но достаточно эффективным подходом для локального улучшения объект- ного кода является так называемая покадровая (или щелевая) оптимизация — метод, нацеленный на повышение производительности объектной программы путем нахож- дения в ней некоторых коротких подпоследовательностей объектных команд (назы- ваемых кадрами) и замены их на более короткие или более быстрые последователь-
Глава 9. Кодогенерация 701 ности там, где это возможно. Покадровая оптимизация рассматривается как техника повышения качества объектного кода, она может также применяться непосредствен- но после генерации промежуточного кода для улучшения промежуточного представ- ления. Кадры просматриваются через небольшое окно (или щель просмотра), перемещаемое по объектной программе. Код в кадре не обязан состоять из последовательных инст- рукций, хотя некоторые реализации требуют этого. Характерно, что покадровая оп- тимизация при своем применении к конкретному коду может привести к появлению возможностей для дополнительных улучшений (как говорят, является оптимизи- рующим преобразованием, повторным по отношению к себе). Поэтому в общем слу- чае повторные просмотры объектного кода являются полезными и позволяют полу- чить более хороший результат. Характерными видами покадровой оптимизации являются: удаление избыточных команд, оптимизации потока управления, алгебраи- ческие упрощения, использование машинных идиом. 9.8.2. Избыточные загрузки и запоминания Если встретилась последовательность команд (1) MOV Ro, а (2) MOV a, Ro можно удалить команду (2), поскольку когда (2) выполняется, команда (1) гарантиру- ет, что значение а уже находится в регистре Ro. Следует заметить, что, если коман- да (2) имеет метку, нет гарантии, что (1) будет исполнено непосредственно перед командой (2), и, таким образом, нельзя удалить (2). Переставив у рассмотренной по- следовательности команды (1) и (2), получаем другую последовательность, для кото- рой возможно это преобразование. Хотя рассмотренную последовательность не следует искать в коде, который сгенери- рован алгоритмом, описанным в разд. 9.4, такое преобразование будет полезным, если используется несколько более простой алгоритм генерации, см. разд. 9.5.1. 9.8.3. Недостижимый код Другая возможность для покадровой оптимизации — это удаление кода, недостижи- мого по управлению. Любая непомеченная команда, непосредственно следующая за командой безусловной передачи управления, может быть удалена. Например, для целей отладки большая программа может иметь внутри себя целые сегменты, кото- рые выполняются, только если некоторая переменная debug принимает значение 1. На языке Си исходный код мог бы иметь вид Hdefine debug О if (debug) { печать отладочной информации
702 Часть II. Применение графов и граф-моделей В промежуточном представлении указанный оператор if может транслироваться сле- дующим образом: если debug = 1 на Ц на 1.2 Ц-. печать отладочной информации 1-2. Очевидной покадровой оптимизацией является удаление передачи управления за пе- редачей управления. Таким образом, независимо от значения величины debug рас- смотренная последовательность может быть заменена на если debug * 1 на L2 печать отладочной информации Теперь, поскольку debug принимает значение 0 в начале программы, оптимизирую- щее преобразование, получившее название втягивание констант, должно заменить указанную последовательность на следующую: если 0 *1 на 1_2 печать отладочной информации 1-2'- Поскольку аргумент первого оператора вычисляет константу истина, этот оператор может быть заменен на оператор на L2. Тогда все операторы, которые печатают отла- дочную информацию, являются явно недостижимыми и могут быть по одному уда- лены. 9.8.4. Оптимизации потока управления Алгоритмы генерации промежуточного кода часто порождают переходы на перехо- ды, переходы на условные переходы и условные переходы на переходы. Эти не яв- ляющиеся необходимыми переходы могут быть удалены как в промежуточном коде, так и в объектном коде с помощью покадровых оптимизаций следующего вида. По- следовательность переходов на Li Li. на L2 можно заменить на последовательность на L2 Li. на L2 Если при этом не остается других переходов на команду с меткой £ь то можно уда- лить команду на £2, если ей предшествует команда безусловной передачи управ- ления. Заметим, что выполнение указанной оптимизации не требует дополнительного просмотра текста, если при построении промежуточного кода помещать в таблицу символов для каждой метки информацию о числе команд передачи управления на
Гпава 9. Кодогенерация 703 данную метку и при дальнейшей обработке эту информацию поддерживаются в пра- вильном состоянии. Подобно этому последовательность если а < b на L-i Lr на L.2 может быть заменена на если а < b на L2 Lr. на L2 Наконец, предположим, что имеется только одна команда перехода на команду с меткой и перед командой с меткой Lt расположена команда безусловный переда- чи управления. Тогда последовательность на Li Lr. если а < Ь на £.2 L3' может быть заменена на последовательность если а < b на L2 на L3 Lr- Число команд при такой замене никак не изменяется, тем не менее такое преобразо- вание полезно, поскольку оно создает дополнительные возможности оптимизации переходов, связанные с возможным удалением команды безусловного перехода. 9.8.5. Алгебраические упрощения Бесконечно число тех алгебраических упрощений, которые можно пытаться приме- нить при покадровой оптимизации. Однако успешного применения в достаточном числе случаев можно ожидать только от небольшого числа алгебраических равенств. Например, такие операторы, как х := х + 0 или х := х * 1, часто порождаются при применении "прямого" алгоритма генерации промежуточного кода, и они могут быть просто удалены покадровой оптимизацией. 9.8.6. Понижение силы операции Понижение силы операций— оптимизирующее преобразование, которое повышает качество кода за счет замен дорогих операций эквивалентными им более дешевыми для данной объектной машины. Некоторые машинные команды заметно дешевле других и часто могут использоваться в качестве специальных случаев более дорогих операций. Например, х2 заметно дешевле реализовать как х * х, а не обращением к процедуре вычисления возведения в степень. Умножение или деление на 2 числа с фиксированной точкой дешевле выполнить с помощью сдвига. Деление на констан-
704 Часть II. Применение графов и граф-моделей ту числа с фиксированной точкой можно реализовать (аппроксимировать) умноже- нием на константу, что может быть дешевле. 9.8.7. Использование машинных идиом Объектная машина может иметь машинные команды для эффективной реализации определенных конкретных операций. Обнаружение ситуаций, которые позволяют использовать эти команды, позволяет заметно сократить время исполнения про- грамм. Например, некоторые машины имеют автоматически увеличиваемые и уменьшаемые виды адресов. Они добавляют (или вычитают) единицу к операнду перед (или после) использования значения операнда. Использование указанных ви- дов существенно повышает качество кода, когда необходимо поднимать или опус- кать стек при подстановке параметров. Эти виды могут также использоваться в коде для оператора, подобного i := i + 1. 9.9. Генерация кодогенераторов Генерация кода включает выбор порядка вычислений для операций, присваивание регистров для хранения величин, а также выбор подходящих машинных команд для реализации операций в промежуточном представлении. Даже если предположить, что порядок вычисления задан и регистры распределены с помощью отдельного ме- ханизма, проблема определения команд может представлять собой сложную комби- наторную задачу, особенно для машин с богатыми возможностями адресации. 9.9.1. Генерация кода и переписывание деревьев Под входом процесса кодогенерации понимается последовательность деревьев на семантическом уровне объектной машины. Это те деревья, которые можно получить после вставки адресов периода исполнения в промежуточное представление, описан- ное в разд. 9.2. Например, на рис. 9.26 представлено дерево для оператора присваивания a[z] := b + 1, в котором а и i являются локальными переменными, чьи адреса периода исполнения даны смещениями consta и const; от SP-регистра, содержащего указатель на начало текущей записи активации. Присваивание «[/] является косвенным присваиванием, в котором r-значение ячейки для а[1] получает r-значение выражения b + 1. Адрес мас- сива а определяется путем добавления значения константы const,, к содержимому регистра SP. b является глобальной переменной, которая размещена в ячейке памяти теть. Для простоты изложения предполагается, что все переменные имеют литерный тип. В дереве операция ind рассматривает свои аргументы как адреса ячеек памяти. Как левый сын операции присваивания вершина ind дает ячейку, в которой должно запо- минаться r-значение правой части операции присваивания. Если аргумент операции "+" или ind является ячейкой памяти или регистром, то содержимое этой ячейки па- мяти или регистра берется как значение. Листья в дереве имеют атрибуты типов с ин- дексами; индекс указывает значение данного атрибута.
Глава 9. Кодогенерация 705 Рис. 9.26. Дерево оператора присваивания Объектный код генерируется в процессе, в ходе которого входное дерево редуциру- ется в единственную вершину путем применения правил переписывания к дереву. Каждое правило переписывания имеет вид замена <— образец {действие}, где заме- на—это некоторая вершина, образец— некоторое дерево, а действие— некоторый фрагмент кода. Множество правил переписывания деревьев называется схемой трансляции деревьев. Каждый древовидный образец представляет вычисление, производимое последова- тельностью команд, получаемых из ассоциированного действия. Обычно образец соответствует одной машинной команде. Листьями образца являются, как и во вход- ном дереве, атрибуты с индексами. Часто накладываются определенные ограничения на значения индексов в образцах; эти ограничения специфицируются в виде семан- тических предикатов, которые должны удовлетворяться при отождествлении образ- ца. Например, предикат может специфицировать определенный диапазон значений, в который попадает значение константы. Схема трансляции деревьев является удобным средством для представления этапа выбора команд кодогенератора. В качестве примера правила переписывания деревьев можно рассмотреть правило команды сложения регистр-в-регистр, представленном на рис. 9.27. Это правило ис- пользуется следующим образом. Если входное дерево содержит поддерево, которое отождествляется с указанным древовидным образцом, т. е. которое имеет корень, помеченный операцией "+", и двух сыновей, являющихся величинами, находящими- ся в регистрах i и у, то можно заменить это поддерево на единственную вершину, по- меченную reg,, и выдать на выход команду ADD Rt, Rt. Возможно, что в некоторый момент с поддеревом может отождествиться более одно- го образца; имеется ряд подходов для выбора применяемого правила в случае таких конфликтов. Предполагается, что распределение регистров выполнено до выбора кода. 23 Зак. 202
706 Часть II. Применение графов и граф-моделей reg, reg. Рис. 9.27. Пример правила переписывания 1. reg-<—constc {MOV #c.RJ {MOV a. R J 2. reg-*—mem^ 3. {MOV R. _aj 6. reg -*----ind {MOV R .*R } i । {MOV c(R). R} i । constc reg. 6 {ADD c(Fp. R ) 8. Рис. 9.28. Правила переписывания деревьев {ADD R.R J i i reg j const, {INC R J На рис. 9.28 изображены правила переписывания деревьев для нескольких команд объектной машины. Эти правила в дальнейшем будут использоваться в других при- мерах этого раздела. Два первых правила соответствуют командам загрузки, сле- дующие два— командам запоминания, а оставшиеся — индексированным загрузкам и сложениям. Следует заметить, что правило 8 требует, чтобы значением константы была единица. Это условие могло бы специфицироваться семантическим преди- катом.
Глава 9. Кодогенерация 707 Схема трансляции деревьев работает следующим образом. Пусть имеется входное дерево. Образцы правил переписывания применяются к его поддеревьям. Если неко- торый образец отождествляется, отождествленное поддерево входного дерева заме- няется на заменяющую вершину правила и выполняются действия, ассоциированные с этим правилом. Если это действие содержит последовательность машинных ко- манд, команды выдаются на выход. Этот процесс повторяется до тех пор, пока дерево не редуцируется к единственной вершине или не будут отождествляться образцы. Последовательность машинных команд, сгенерированных в процессе редукции вход- ного дерева к вершине, образует выход схемы трансляции деревьев для заданного входного дерева. Процесс спецификации кодогенератора становится подобным тому, который исполь- зуется в схеме синтаксически ориентированной трансляции для спецификации транслятора. Фактически готовится схема трансляции деревьев для описания систе- мы команд объектной машины. На практике, однако, ищется такая схема, которая приводит к последовательности кода минимальной стоимости при генерации каждо- го входного дерева. Доступен ряд средств, ориентированных на поддержку автома- тического построения кодогенератора по схеме трансляции деревьев. Рассмотрим схему трансляции деревьев на рис. 9.28 в ее применении к генерации кода для входного дерева, изображенного на рис. 9.26. Предположим, что первое пра- вило rego <— const,, {MOV #a, /?о} применяется для загрузки константы а в регистр Ro. Тогда метка самого левого листа изменяется с const, на reg0, и генерируется команда MOV#a, Ro. Седьмое правило теперь отождествляется с левым поддеревом с корнем, помеченным "+", и примет вид, изображенный на рис. 9.29. Использование этого правила заменяет это поддерево на единственную вершину, помеченную reg, и генерируется команда ADDSP, Ro. После этого дерево примет вид, изображенный на рис. 9.30. re9£ {ADD SP, RJ re9o re9sp Рис. 9.29. Вид седьмого правила после отождествления К указанному дереву можно применить правило 5 (см. рис. 9.28) для редукции подде- рева, изображенного на рис. 9.31, к единственной вершине, помеченной символом regi. Однако также можно использовать правило 6 (см. рис. 9.28) для редукции большего поддерева, изображенного на рис. 9.32, в единственную вершину, помеченную reg0, и генерации команды ADD i(SP), Ro. Предполагая, что более эффективным является использование единственной коман- ды для вычисления большего поддерева, следует выбрать меньшую редукцию для получения, изображенного на рис. 9.33. В правом поддереве полученного дерева правило 2 (см. рис. 9.28) применимо к листу memfc. Это правило генерирует команду загрузки b в регистр 1. Теперь правило 8
708 Часть II. Применение графов и граф-моделей Рис. 9.30. Преобразованное дерево Рис. 9.31. Редуцируемое поддерево Рис. 9.33. Результат редукции отождествляется с поддеревом, изображенным на рис. 9.34, и генерируется команда INCR\. В этот момент входное дерево примет вид, представленный на рис. 9.35. К текущему виду дерева применимо правило 4, которое редуцирует дерево к единст- венной вершине и генерирует команду MOV R\, *R0. В процессе редукции дерева к единственной вершине порождается следующая по- следовательность команд MOV#a, Ro ADD SP, Ro ADD i(SP), Ro
Гпава 9. Кодогенерация 709 MOVb, Ri INC Ri MOV Ri, * Rq reg 1 const 1 rego Рис. 9.35. Результат редукции Рис. 9.34. Поддерево Ряд аспектов этого процесса редукции дерева нуждается в дальнейшем пояснении. Пока не специфицировано, как производится процесс отождествления. Не специфи- цирован порядок, в котором образцы отождествляются, и не определено, что проис- ходит, когда отождествимо несколько образцов одновременно. Нужно заметить, что если нет отождествляемых образцов, процесс кодогенерации блокируется. Другой крайний случай, который возможен для единственной вершины, — это когда процесс продолжается бесконечно, порождая неограниченную последовательность команд пересылки регистров или неограниченную последовательность загрузок и запоми- наний. Один из путей для того, чтобы сделать процесс отождествления древовидных образ- цов более эффективным, состоит в расширении алгоритма многоключевого поиска по образцу в алгоритм поиска древовидных образцов сверху вниз. Каждый образец может быть представлен множеством строк, а именно, множеством путей от корня к листьям. Из этих наборов строк можно сконструировать унификатор древовидных образцов. Проблемы упорядочения и многократных отождествлений могут разрешаться по- средством соединения отождествления древовидных образцов с алгоритмом динами- ческого программирования, описанном в разд. 9.8. Схема трансляции деревьев может снабжаться стоимостями машинных команд, генерируемых, если соответствующие правила применяются. На практике процесс переписывания деревьев может реализовываться, выполняя унификатор древовидных образцов во время обхода в глубину входного дерева и осуществляя редукции, когда вершины посещаются последний раз. Если при этом применяется алгоритм динамического программирования, можно выбрать оптималь- ную последовательность, используя стоимостную информацию, ассоциированную с каждым правилом. Необходимо откладывать решение по отождествлению до тех пор, пока не станут известными стоимости всех альтернатив. При использовании этого подхода небольшой эффективный кодогенератор можно быстро реализовать по схеме переписывания деревьев. Более того, алгоритм динамического программирования освобождает разработчика кодогенератора от необходимости разрешения конфлик- тов при поиске по образцу и определения порядка вычисления.
710 Часть II. Применение графов и граф-моделей 9.9.2. Поиск по образцу при разборе Другой подход связан с использованием /./^-анализатора для выполнения поиска по образцу. Входное дерево можно рассматривать как строку в префиксном представле- нии. Например, префиксное представление для дерева на рис. 9.21 имеет вид := ind + + constu regS;> ind + const, regs/> = mem/, const,. Схема трансляции деревьев может конвертироваться в схему синтаксически ориен- тированной трансляции путем замены правил переписывания деревьев на правила контекстно-свободной грамматики, в которой правыми частями являются префикс- ные представления древовидных образцов. Схема синтаксически ориентированной трансляции на рис. 9.36 основывается на схе- ме трансляции деревьев, изображенной на рис. 9.28. 1. reg, -> const,. {Л/ОГ#с,/?,} 2. reg, —> mem„ {МОИa, R,} 3. mem := mem^reg. {MOV R„ a} 4. mem -> := ind reg, reg, {MOV Rj, *R,} 5. reg, ind + const,, reg, {MOVc(Rj), R,} 6. reg, -> + reg, ind + const, reg, {ADD c(R,), /?.} 7. reg,—> +reg, reg, {ADD Rj,R,} 8. regj -> + regj const । {INC /?,} Рис. 9.36. Схема синтаксически ориентированной трансляции По правилам схемы трансляции строится /./^-анализатор при использовании одного из известных методов конструирования /./^-анализаторов. Объектный код генериру- ется выдачей машинных команд, соответствующих каждой редукции. Грамматика для кодогенерации обычно сильно неоднозначна, и надо при конструи- ровании анализатора уделять специальное внимание тому, как разрешить конфликты в процессе разбора. При отсутствии информации о стоимости общим правилом явля- ется то, что большая редукция лучше меньшей. Это означает, что в конфликте редук- ция-редукция предпочтение отдается более длинной редукции, а в конфликте сдвиг- редукция выбирается сдвиг. Этот подход "наибольшего откусывания" приводит к увеличению числа операций, которые выполняются с одной машинной командой. Существует ряд аспектов, связанных с использованием /./^-анализа для кодогенера- ции. Во-первых, указанный метод разбора является эффективным и хорошо понят- ным, так что надежные и эффективные кодогенераторы могут быть построены с ис- пользованием соответствующих алгоритмов. Во-вторых, относительно несложно пе- ренацелить результирующий кодогенератор; выбор кода в кодогенераторе для новой машины можно сконструировать путем написания грамматики, описывающей ко- манды указанной машины. В-третьих, качество сгенерированного кода можно повы-
Глава 9. Кодогенерация 711 сить, добавив специальные продукции для получения преимуществ от машинных идиом. Вместе с тем имеются также определенные трудности. Метод разбора фиксирует по- рядок вычисления слева направо. Кроме того, для некоторых машин с большим чис- лом видов адресации грамматика, описывающая машину, и результирующий анали- затор могут принять необычные размеры. Как следствие, возникает необходимость в специализирующих технологиях, которые можно было применять в грамматиках, описывающих машины. Необходимо при этом заботиться, чтобы результирующий анализатор никогда не заклинивался (имел следующий шаг) во время разбора дерева выражений из-за того, что грамматика не обрабатывает некоторых образцов опера- ций или анализатор сделал неправильный выбор при решении некоторого конфликта при выполнении разбора. Также нужно добиться гарантий, чтобы анализатор не впа- дал в бесконечный цикл редукций с одним символом в правой части. Проблемы за- цикливания можно разрешить с использованием метода расщепления состояний во время генерации таблиц разбора 9.9.3. Процедуры семантической проверки Листья входного дерева являются атрибутами типа с индексами, в которых индекс ассоциирует некоторое значение с атрибутом. В схеме трансляции кодогенерации появляются одни и те же атрибуты, но часто с ограничениями на то, какие они могут иметь значения. Например, некоторая машинная команда может требовать, чтобы значение атрибута попадало бы в определенный диапазон или чтобы значения двух атрибутов были связаны. Указанные ограничения на значения атрибутов могут специфицироваться с помощью предикатов, которые вызываются до выполнения редукции. Фактически общее ис- пользование семантических действий и предикатов может предоставить больше гиб- кости и простоты в описании, чем чисто грамматическая спецификация кодогенера- тора. Родовые образцы можно использовать для представления классов команд, и семантические действия могут тогда использоваться для отнесения инструкций к конкретным классам. Например, две формы команды сложения можно представлять одним образцом, изображенном на рис. 9.37. {если с=1 то INCRj иначе ADD # c.RJ Рис. 9.37. Правило переписывания для сложения Конфликты времени разбора можно решать с помощью снимающих неоднозначности предикатов, которые могут разрешать различным стратегиям выбора использоваться в различных контекстах. Возможно также уменьшить описание объектной машины, поскольку определенные аспекты машинной архитектуры, такие как виды адресации, могут быть вынесены в атрибуты. Трудность рассмотренного подхода состоит в том,
712 Часть II. Применение графов и граф-моделей что может затрудниться верификация точности атрибутной грамматики как правиль- ного описания объектной машины, хотя указанная проблема в топ или иной степени является обшей проблемой всех кодогенераторов. 9.9.4. Покрывающие деревья При применении правил переписывания образцы поддеревьев наряду с вершина- ми исходного дерева, которые называют операторами, могут содержать в качестве листьев и такие вершины, которые в исходном дереве отсутствовали и как бы появи- лись в результате предыдущих применений правил. Эти новые вершины, называемые результирующими вершинами или нетерминалами, представляют результаты вычис- ляемыми командами, связанными с соответствующими образцами, и используются для выражения взаимосвязи между образцами поддеревьев. Процесс редукций ис- ходного дерева с помощью правил переписывания продолжается, пока они примени- мы, т. е. пока не будет получена единственная вершина. Рис. 9.38 содержит пример возможного применения к дереву (см. рис. 9.30) правил переписывания, приведенных на рис. 9.28. Здесь в рамки заключены фрагменты дерева, сопоставленные образцам правил, номера которых указаны в левых верхних углах рамок, а результирующие вершины указаны в квадратных скобках. Другая трактовка правил переписывания заключается в том, что они при своем при- менении "стягивают" фрагменты исходного дерева, сопоставляемые образцам правил
Глава 9. Кодогенерация 713 переписывания, в отдельние вершины дерева, которые метятся номерами соответст- вующих правил. Результирующее дерево, называемое покрывающим, сохраняет ин- формацию о структуре исходного дерева для последующих этапов генерации кода, например для распределения регистров. Осуществив покрывающее дерево в обрат- ном порядке и используя метки его вершин, можно осуществить порождение кода отдельно для каждой вершины. Возможное покрытие дерева (см. рис. 9.30) правила- ми (см. рис. 9.28) изображено на рис. 9.38; соответствующее этому покрытию покры- вающее дерево приведено на рис. 9.39. Покрывающее дерево Т исходного дерева D называется Л-покрытием. если корень дерева Т помечен правилом, имеющим резуль- тирующую вершину А. Процесс нахождения покрывающего дерева является недетерминированным, по- скольку в общем случае можно построить множество возможных покрытий для од- ного и того же исходного дерева. Поэтому задачей выбора команд становится нахож- дение подходящего покрытия, соответствующему лучшему способу реализации того или иного действия (или последовательности действий). При этом может вводиться понятие веса (стоимости) правила, связанного с качеством кода, генерируемым при использовании указанного правила, и тогда задача нахождения "подходящего" по- крытия может формулироваться как задача нахождения покрывающего дерева наи- меньшего веса. Правило 4 Правило 6 Правило 7 Правило 8 Правило 2 Правило 1 Рис. 9.39. Покрывающее дерево 9.9.5. Система BEG В системе BEG, ориентированной на генерации эффективных генераторов кода, пра- вила переписывания имеют следующую форму: RULE образец -> резулыпирующая_вершина [CONDITION условие_применимости_правила;] COST целое_число — вес_команды, [EMIT машинная_команда и/или формупы_вычиспения_атрибутов,] Например, правило для команды INC будет иметь вид: RULE + reg const -> reg CONDITION (const, value = 1) C0S71; EMIT {вывод команды INC R,, где R, = reg.registert},
714 Часть II. Применение графов и граф-моделей где дерево изображено в постфиксной нотации, а через указываются атрибуты операторов. Предполагается, что атрибуты операторов, определяемые на этапе порождения дере- ва, можно использовать в условиях применимости и ЕЛУ/Т-действиях; £Л//Г-действия генерируют объектный код и/или вычисляют значения синтезируемых атрибутов в процессе вывода кода; синтезированные атрибуты доступны только внутри EMIT- действий и используются, например, для вычисления кода для способа адресации операндов. Как правило, объектная ЭВМ допускает несколько способов адресации операндов, которые можно использовать в большом числе различных команд. Если пытаться использовать отдельный нетерминал для каждого способа адресации и задавать от- дельное правило переписывания для каждой комбинации способа адресации и каж- дой команды, можно прийти к необходимости построения громадного числа правил переписывания. Поэтому в системе введено понятие так называемого цепного прави- ла переписывания, т. е. правила, в котором образец состоит из единственного нетер- минала, с ориентацией на следующее применение. Создается одно правило перепи- сывания для каждой команды, в котором операнды описываются нетерминалами, представляющими все способы адресации или их выделенную часть; нетерминалы, представляющие отдельные из этих способов адресации, выводятся из первых с по- мощью цепных правил. Задача нахождения оптимального покрытия дерева решается следующим образом. Для каждой вершины и дерева Т и для каждого нетерминала А вычисляются зна- чения: с„^ — вес минимального /1-покрытия поддерева дерева Тс корнем и, гм — номер правила, которым помечен корень этого /-покрытия. Если /-покрытия поддерева не существует вообще, то с„^ принимает значение, пред- ставляющее бесконечность, а значение не определено. Значения с„^ и г„^ вычисляются для вершин исходного дерева снизу вверх, начиная с его листьев. Для каждой вершины п дерева вначале рассматриваются все нецепные правила, имеющие образец, сопоставляемый с поддеревом с корнем и. Пусть таким правилом является некоторое правило г : О0О\А\О2А2,..., ОрАк —> А с результирующей вершиной А и образцом, в который входят нетерминалы At,A2,..., Ак и операторы О2, ..., Ор. В результате предыдущих шагов процесса вычисления покрытия вершинам щ, п2,пк сопоставлены нетерминалы А\, А2,..., Ак и вычислены значения спЛ (см. рис. 9.40, где вершины /иь т2, тк дерева помечены операторами О,, О2, ..., Ор соответственно). Тогда вес данного /-покрытия поддерева вычисляется к как Cr = eec npaewia r + л . Если г0 — правило, для которого значение Сг ми- ,=i нимально, то вычисляются = СГ) и г'„^ = г0. После того как рассмотрены все пра-
Глава 9. Кодогенерация 715 вила, не являющиеся цепными, обрабатываются цепные правила следующим обра- зом. Сначала устанавливается с„^ = с'„А и = г'„^. Затем, пока существуют правила г: В А некоторой стоимости С, для которых сПгА > С + спд, устанавливается С + Cftц И t П>А Г* Рис 9.40. A-покрытие поддерева 9.10. Генерация оптимального кода для стековых машин Пусть имеется машина с некоторым фиксированным числом арифметических реги- стров, сконфигурированных в виде стека. Предполагается существование основной памяти произвольного доступа для хранения промежуточных результатов и началь- ных данных. Цель оптимальной кодогенерации состоит в такой организации вычис- ления арифметического выражения, при которой минимизируется обмен информаци- ей между стековой и основной памятью. 9.10.1. Стековая машина и корневые деревья Множество допустимых команд рассматриваемой стековой машины состоит из трех команд: PUSH 8, POP 8 и OP(Q, где 8— адрес ячейки основной памяти, а обозна- чаетр-арную операцию. Пусть /?[1],.... /?[7V] обозначают имеющиеся арифметические регистры, где N— некоторое фиксированное положительное число, Л-/[1], Л7[2],..., M[N] обозначают ячейки основной памяти, и ТОР обозначает регистр верха стека (ТОР = 0 означает, что стек пуст, и ТОР = N означает, что стек полон). Тогда указан- ные операции имеют следующую семантику: PUSH 8 ТОР <- ТОР + 1 R(TOP) <- ЛД5)
716 Часть II. Применение графов и граф-моделей POPS ОР& Л7(8) <- R(TOP) ТОР <- ТОР -1 ТОР +-ТОР-р + 1 R(TOP) <- ^(R(TOP), ..., R(TOP + р - 1)), гдер > 1 — арность операции Рис. 9.41. Дерево выражения Для вычисления выражения ((а / (Ь + с)) - (d * (е +./))), дерево которого изображено на рис. 9.41, можно при /V= 2 использовать следующую последовательность сгенери- рованных команд: Программа Р Содержимое стека 0. 0 (т. e. пустой стек) 1. PUSHb b 2. PUSH с b, с 3. ОР(+) (b + c) 4. POP 11 0 5. PUSHе e 6. PUSHf e,f 7. OP (+) (e +/) 8. POP 12 0 9. PUSH d d 10. PUSH 12 d, (e +f) 11. OP(*) (d*(e +/)) 12. POPUS 0 13. PUSH a a
Гпава 9. Кодогенерация 717 14. PUSH I 1 15. ОРЦ) \6.PUSHt3 17. ОР(-) а, {Ь + с) (а/(Ь + с)) (g/(Z? + c)), (d*(e+f)) ((a/(b + с)) - (d * (е +/))) Пусть т = (V,D,r)— упорядоченное корневое дерево, в котором И — множество вершин, г — корень, a D — отображение, сопоставляющее каждой вершине v е V последовательность D(v) = vb ..., vp ее сыновей. Пусть Р(т) обозначает последова- тельность вершин дерева Т| перечисленных в постфиксном упорядочении, т. е. Л(т)— это г, если г не имеет сыновей, и обозначает Р(т,), ..., Р(тД если D(y) = v>, ..., v„ и гj — поддерево дерева т с корнем v,. Вершина и является левы м сыном (непосредственным потомком) вершины v в дере- ве т, если D(v) = и,..., w и левым потомком v, если существует левый путь от v до и, т. е. такой путь о г v до и, в котором каждая следующая вершина является левым сы- ном предыдущей. Пусть Н'с И. Вершина v е I называется непосредственным потомком W, если vg II' и v— сын некоторой вершины из W. IV—левое множество дерева т, если существу- ет такой левый путь ..., и>, в т, что W = {w,, ..., w,}. Апексом дерева т называется такое дерево t'=(v', D',r), что V с V и для любого v е V, если D'(y) # 0, то D’(y) = D(v). Частичным деревом дерева т называется некоторый апекс поддерева т. Пусть v— некоторый сын и, т. е. D(u) = vb ..., vp, где v, = v для некоторого i. Тогда i d(u, v) = /- 1. Если (m'i, ..., и’,)— некоторый путь из и к v, то d(u,v')-'^'d(w,_l,wj). 1=2 Иначе d(u, v) не определено. Например, в дереве, изображенном на рис 9.42, а, вершина 4 является левым потом- ком вершины 1, вершина 6— непосредственный потомок множества {1, 2, 3}, {1, 2, 4} является левым множеством, d(\, 2) = 0 и <7(2, 9) = d(2, 5) + <7(5, 9) = 2. Рис. 9.42. Деревья выражений
718 Часть II. Применение графов и граф-моделей 9.10.2. Стековые вычисления Пусть имеется дерево т и его постфиксный обход Р(т). Вычисление, связанное с Р(т) = иь и„„ задается стековой последовательностью Ro', Rf,...; R,,„ определяемой по следующим правилам: начало 1. Ro :=0; 2. для / := 1 до m цикл 3 если D(ui) = v-i,..., vpto 4. Rj := R'i, и,, где R', получается из R,-i удалением p термов с правого конца R; 1 иначе R, := R,i, u, все все конец Каждый терм в Ро; /?,;Rn, является состоянием стека во время вычисления, связан- ного с Р(т). Последовательность Р(т) моделирует вычисление т, использующее только команды PUSH и ОР. Программа Р, которая вычисляет т, является последовательностью вида P=P(b), Т, Р(т2), Т, Р(т,.), в которой: □ s > I; □ т, = (К„ D„ г,) — частичное дерево дерева т для z = 1, s; П tv — апекс дерева т; П для всех v е V, если v е V„ D,(y) = 0 и D(y) * 0, то существует единственный но- мер j < i, такой, что rt = v. В этом случае говорят, что дерево т, зависит от дере- ва т7. Последовательности Р(т,) называются сегментами Р. Обозначение Т используется для описания того, что после каждого сегмента результирующая вершина в стеке удаляется и сохраняется в основной памяти. Эта вершина позднее может использо- ваться во время вычисления некоторого другого частичного поддерева т Пусть Р = P(ji), ?,Т, Р(т,.) — некоторая программа, вычисляющая т. Сегмент Р(т/) называется необходимым, если либо т, зависит от т7, либо существует некоторый не- обходимый сегмент т„ который зависит от т7. Ясно, что не будут оптимальными про- граммы, которые содержат сегменты, не являющиеся необходимыми. Поэтому в дальнейшем под Р понимается только такая программа, в которой каждый сегмент необходим. Вычисление, связанное с Р = щ,ит, задается стековой последовательностью Ro', R\', Rmi
Гпава 9. Кодогенерация 719 определяемой по следующим правилам: начало 1 Ro = 0, 2 . для / - 1 дот цикл 3 если и, = ? то R, =0 4 . иначе если D(u,) = Vi. ур то 5 Ri := R'i, Ui, где R', получается из R, 1 удалением p термов с правого конца R,_j 6 . иначе R, := R, 1, u, все все все конец Пусть т = (И, D, г) некоторое дерево и N— положительное число, которое специфи- цирует максимальную глубину стека. Пусть о(т, N) — множество всех программ Р, которые вычисляют т и для которых |/'| < N, где |/' | — максимальная глубина стека в процессе вычисления, связанного с Р, т. е. |Р| = тах{|Р(т,)|: 1 <i<s}. Ясно, что о(т, N) является пустым, если существует некоторая вершина у, для кото- рой D(y) = У|,vr ир> N. Пусть а(т) = max{p : v е V и /)(у) = уь у,,}. Если W > ос(т), то о(т, /V) не пусто, по- скольку можно построить программу/5 = Р(Т|),?, ...,Т, /’(т,), которая вычисляет т и в которой каждое частичное дерево имеет вид (V', D', у), где £>(у) 0, D(v) = уь ..., vp, V' = {у, у,,..., ур}, D'(y) = £)(у) и D'(y,) = 0 для j = 1, ..., р. Ясно, что | Р | = ос(т). Говорят, что Р является N-onrmiMcuibiioii программой относительно т, если: □ /’ео(т, 7V); □ у(Р) < у(/>') для всех Е”ео(т, /V), где у(Р) обозначает так называемую стоимость программы Р, которая определяется как число сегментов в Р минус единица. Рассмотрим простой алгоритмом, который использует функцию разметки L для вы- числения снизу вверх требований к стеку поддеревьев т. В процессе его работы каж- дый раз, когда находится поддерево, которое превышает емкость стека N, сегмент генерируется, соответствующее поддерево отсекается и процесс разметки продолжа- ется. Алгоритм 9.4 Дано. Дерево т = (V, D, у) и положительное целое /V> а(т). Требуется. /V— оптимальная относительно т программа Р. Метод. процедура TYPE0 (у : вершина) = 1. % D(v) = Vi,.... vp и г, является поддеревом с корнем у, дерева т, где 1 <i<p %;
720 Часть II. Применение графов и граф-моделей 2. Пусть Кик — такие целые, что К = L(vk) + к-1 = max{L(v,) + /-1 : / е [1, р]}, 3. если К < N то L(v) := К 4. иначе Р <= Р(тк),Т; V := V\{u : и- потомок vk}; 5. г := апекс т с множеством вершин V; Цуь) := 1 все все; начало 1 для всех v из V цикл 2. если D(v) - 0 то L(v) := 1 иначе L(v) := 0 все все; 3. Р := 0; 4 пока L(r) = 0 цикл 5. Пусть v— такая вершина, что L(v) = О и, если и — непосредственный преемник v, то Ци) * 0; 6. TYPEO(v) все, 7. Р<=Р(т) конец Пусть т является деревом, изображенным на рис. 9.42, а, и пусть Л'= 3. Начальная его разметка указана на рис. 9.54, б. При первом выполнении цикла 4-6 имеем v = 5, р = 3, г, = 8, v2 = 9 и v3 =10; в TYPE0 вычисляется К = 3 и к = 3; таким образом 6(5) становится равным 3. При следующей итерации v = 2, р = 2, г, = 4 и v2 = 5. На этот раз К = 4 и к - 2. Следовательно генерируется сегмент для поддерева т с v2 = 5 и, таким образом: О 6 = 8,9, 10, 5, t; О У= {1,2, 3,4, 5, 6, 7}; О т имеет вид, изображенный на рис. 9.42, в с 6(5) = 1. Вычисление затем продолжается и очевидно получается 6(1) = 3. Результирующей является программа Р = 8, 9, 10, 5, Т, 4, 5, 2. 6, 7, 3, 1. 9.10.3. Коммутативные операции Пусть т = (И, D, г)— дерево и С— такое подмножество V, что D(v) У 0 для всех v е С. Вершины из С называются коммутативными и соответствуют коммутатив- ным операциям в том смысле, что их операнды могут находиться на стеке в любом порядке. Пусть £(т, С) — класс деревьев, которые можно получить из т переупорядо- чением непосредственных преемников коммутативных вершин из т, и пусть о(т, С, N) = {6 : Р е с (т', N), V Е (т, Q}. Программа Р называется W— оптимальной относительно т и С, если Ре о (т, С, N) и у (6) < у (Р') для всех Р’ е о (т, С, N). Рассмотрим алгоритм, который воспринимает в качестве входа т, С, N и выдает ^оптимальную программу относительно г и С. Структурно он подобен алгоритму,
Глава 9. Кодогенерация 721 рассмотренному в разд. 9.4, в том смысле, что он обрабатывает т снизу вверх, пере- упорядочивает непосредственных потомков вершин в С для нахождения минималь- ных требований к стеку и подрезая т, когда находятся поддеревья с избыточными требованиями к стеку. Алгоритм 9.5 Д а н о. т = (К, D, г) — дерево, Сс Ии положительное число N> а (т). Множество С является таким, что D (v) * 0 для всех v е С. Требуется. /V-оптимальная относительно т и С программа Р. Метод. процедура TYPE1(v: вершина) = 1 % D(v) = Vi, .... vp и т,— поддерево дерева г с корнем v, для всех 1 < / < р %; 2 Пусть й, .... ip — такая перестановка 1,.... р, 4toL(i/(i) > ...>L(v,p); 3 Пусть Кик — такие целые числа что К = L (vik) + к -1 = max{L ) +/ -1 : 1 <j < р}, 4 если К< Л/то L(v) := К, D(v) v,p 5 . иначеР<= Р(т(1),Т; V :=V\{u:u — потомок (v())}; 6 . т := апекс т с множеством вершин V; Ц (v,.)) := 1 все все; начало 1. для всех v из V цикл если D(v)=0 то L(v) := 1 иначе L(v) := 0 все все; 2. Р = 0; 3 пока L(r) = 0 цикл 4. Пусть v — такая вершина, что L (и) = 0 и если и — непосредственный преемник v, то Ци) ф 0; 5. если v Сто ТУРО(и) иначе TYP1(v) все; 6 Р <= Р(т) все конец 9.10.4. Ассоциативные коммутативные операции Пусть т = (V, D, г) — дерево и А = {Аь ..., А>,} — набор попарно различных подмно- жеств V, таких, что, если v е А„ \ <i<h, то D(v) 0. Элементы А, называются ассо- циативно-коммутативными вершинами и соответствуют ассоциативно-коммута- тивным операциям некоторого одного и того же типа из h рассматриваемых различ- ных типов.
722 Часть II. Применение графов и граф-моделей Кластером с корнем w дерева т называется максимальное множество вершин W, удовлетворяющих следующим свойствам; □ IVci А, для некоторого i е [1, Л]; П IV— множество вершин частичного дерева т с корнем w. Дерево т'= (К, О', г') является перестановкой дерева т, если найдется такое множест- во IV, что П IV — кластер как т, так и т'; П если D(y) = х, w, у, где w— корень IV в т и х и у являются последовательностями вершин, то D'(v) = х, w', у, где w' — корень IV в т'; □ для всех v g W число сыновей v в т равно числу сыновей у в т'; □ для всех v g W, если D(v) Ф х, w, у. то O'(v) = О(у). Рассмотрим дерево т, изображенное на рис. 9.43, а, в котором заштрихованные вер- шины принадлежат множеству At. В дереве т имеется два кластера. Дерево т' (см. рис. 9.43, б) является перестановкой т относительно кластера IV = {а, Ь, с}. а) б) Рис. 9.43. а — исходное дерево, б — его перестановка Пусть £(т, А) — множество всех деревьев, которые можно получить из т некоторой последовательностью перестановок, £(т, С, А) — {т': т' е £(т" С) и т"е £(т, А)} и о(т, С, A, N) = {Р. Р е о (т', 7V) и т'е £ (т, С, Л)}. Р является N-оптимальной относительно т, С и А, если Р е (т, С, A, N) и у (Р) < у (Р') для всех Р' е о (т, С, A, N). Для любого дерева т и положительного целого N справедливы следующие свойства: А. Если Р е о (т, 7V), то существует такая программа Р'е о (т, 7V), что у (Р') < у (Р) и для всех сегментов Р (т') программы Р' корень т' не является левым сыном любой вершины в т.
Гпава 9. Кодогенерация 723 Б. Если Р е о (т, N), то существует такая программа Р' е ст (т, С, A, N), что у(Р') < < у (Р) и для всех сегментов Р (уг) программы Р', если IV— некоторый кластер т', то Wявляется левым множеством относительно т'. В. Если Р е о (т, N), то существует программа Р' е о (т, С, A, N), для которой у (Р') < у (Р) и если W— некоторый кластер т, то существует такой сегмент Р (т') программы Р’, что все вершины из W и все вершины, являющиеся непосредственны- ми потомками IV, находятся в т'. Г. Пусть т = (И, D, г) является деревом, a Ro', R}~, ...; R,„— это стековая последова- тельность, соответствующая Р (т) = И|,и1п. Пусть v — некоторая вершина т и Р (т) имеет вид щ,..., ик, Р (?'),..., и„„ где т' — поддерево т с корнем v. Тогда число тер- мов в Rk (т. е. число занимаемых элементов стека) равно d (г, v). Алгоритм 9.6 Дано. Дерево т = (К, D, г), СсГ, А = {Аь Ак} и некоторое положительное Л'><7(т). Множества At, Ak, С— попарно не пересекаются, и если v— элемент одного из этих множеств, то D(y) * 0. Требуется. Программа Р, являющаяся TV-оптимальной относительно т, С и А. Метод. проц TYPE2(v: вершина) = 1. % v является корнем кластера IV, v-i,..., vp— потомками W, a ti, .... тр— поддеревьями дерева т с корнями Vi,..., vp соответственно % 2. Пусть v,i,.... ViP и vyi,.... VjP являются такими перестановками Vi,..., vp, что L(v,i) > ... > T-(Vjp) и d(v,vy1) <... < d(v,vjp). 3. К := max{L(V;,) + d(v,vji): I <= [1 ,p]} 4. если К < N то 5. Переупорядочить непосредственных потомков W таким образом, чтобы d(v,v,i) < ... < d(v,vyp); 6. L(v) := К; 7. иначе Р <= Р(ти),Т,; V := И{и: и — потомок Ул}; 8. т := апекс т с множеством вершин V; L(v,i) := 1 все все; начало 1. Осуществить перестановку т так, чтобы каждый кластер т стал левым множеством, и пусть г обозначает корень результирующего дерева; 2. для всех v из V цикл если D(v)= 0 то Цу) := 1 иначе L(v) := 0 все все; 3. Р:=0; 4. пока L(r)=O цикл 5. Пусть v — такая вершина, что L(v) = О и выполнено одно из следующих двух условий: (i) v— корень некоторого кластера W дерева т и L(u) * 0, если и — непосредственный потомок W,
724 Часть II. Применение графов и граф-моделей (ii) у не является ассоциативно-коммутативной вершиной и L(u) * 0, если и — потомок у, 6. если v — ассоциативно-коммутативная вершина то TYPE2 7. иначе если у е Сто TYPE 1 (у) иначе TYPEO(y) все все, 8. Р<=Р(т) все конец Рис. 9.44. Исходное дерево Пусть в дереве т, изображенном на рис. 9-44, вершины ст, b и с образуют кластер, а другие вершины не являются ни коммутативными, ни ассоциативно-коммуга- тивными. Пусть N=2. Вначале осуществляется переупорядочение т так, чтобы кла- стер сформировал левое множество (см. рис. 9.45; здесь и рядом с каждой вершиной i указано значение /.(/)). После двух исполнений цикла пока находится кластер W ~ {a, Ь, с}, р = 4, vi=3. у2 = 4, Уз = 5, v4 = 6 Перестановками у,ь ..., vv, и v/b vlr являются 4.6.3.5 и 3,4,5,6 соответственно. Таким образом, К = 3. Поскольку К > 2, генерируется сегмент Р(т,|), где т;( является поддеревом т с корнем 4, т. е. /’ = 7.8,4,Т. Результирующее дерево т показано на рис. 9.46. Следующая итерация цикла пока связана с нахождением кластера W - {о, Ь, с}, вер- шин 3,4,5,6 и перестановок 6,3,4,5 и 3,4,5,6. Значением К является 2 и, следовательно, помечается корень IV и переупорядочиваются поддеревья, соответствующие переста- новкам. Результат показан на рис. 9.47. Две последующие итерации оператора цикла пока устанавливают 7.(1) равным 2 и порождают программу Р, которая в конечном счете будет иметь вид Р = 7,8,4, Т, 9,10,6,3, с, 4, Ь, 5,0,?, 2, ст, 1
Гпава 9. Кодогенерация 725 Рис. 9.45. Переупорядоченное дерево Рис. 9.46. Вид дерева после двух итераций Рис. 9.47. Вид дерева после третьей итерации Библиографический комментарий Генерация кода— наименее изученная фаза трансляции. Исследование проблем, относимых к генерации кода в транслирующих системах, проводится в нескольких основных направлени- ях [4, 14]: модельная генерация кода, интерпретирующая генерация кода и таблично- управляемая генерация кода. Первое направление наиболее широко используется при исследовании математических про- блем в генерации кода. Эти исследования направлены на получение оптимального кода и ана-
726 Часть II. Применение графов и граф-моделей лиз сложности алгоритмов кодогенерации. Поскольку возникаемые здесь проблемы очень сложны и приводят к Л’Р-полным проблемам в более или менее общих постановках, рассмат- риваемые модели генерации кода исследуются для очень простых моделей вычислений, кото- рые далеки от реальных машин и языков программирования Поэтому существующую на сего- дняшний день теорию нельзя прямо применять в реальных генераторах кода. Однако модель- ная генерация кода подсказывает ряд принципов организации кода, и ее можно использовать для определения стратегии предварительного планирования. Концепция интерпретирующей генерации кода состоит в том. что генерация производится в два этапа. На первом этапе порождается код некоторой виртуальной машины. Затем этот код преобразуется в код реальной целевой ЭВМ. Согласно этой концепции для реализации М язы- ков на W машинах понадобится N+M трансляторов. Это число составляют N компиляторов на язык виртуальной машины и М трансляторов с промежуточного языка для целевых машин. Не пользуясь указанной методикой, пришлось бы разрабатывать NxM трансляторов по одному для каждой нары "исходный язык— целевая ЭВМ". Выбор термина "интерпретирующая гене- рация кода" обусловлен тем. что очень часто трансляторы второго этапа являются не компиля- торами, а интерпретаторами. Именно такой подход используется для реализации языка Java, и команды виртуальной Java-машины выполняются соответствующим интерпретатором на каж- дой целевой ЭВМ. Основной идеей таблично-управляемой генерации кода является строгое разделение машинно- независимого алгоритма генерации кода и машинно-зависимой информации, описывающей целевую ЭВМ Такая информация представляется как набор некоторых множеств характери- стик целевой ЭВМ, называемых таблицами образцов. Эти таблицы строятся в период, предше- ствующий трансляции, называемый периодом метагенерации. Алгоритм интерпретирующей генерации кода интерпретирует команды виртуальной машины посредством команд целевой ЭВМ, в то время как в алгоритме таблично-управляемой генерации кода интерпретация заме- няется анализом соответствия между фрагментами промежуточного представления исходной программы и выбранными из таблицы образцов Для такого анализа используются либо мето- ды эвристического поиска, либо методы синтаксического анализа Кодо! енерации посвящен ряд обзорных статей [4, 24, 74, 75, 119]. Вопросы кодогенерации и ее связь с другими этапами трансляции рассмотрены в [I, 2, 7, 11, 12, 15, 23,62, 120]. Работы [27, 29, 124] обсуждают генерацию кода для языков Паскаль, PL.8 и Блисс. Знание свойств класса транслируемых программ полезно для успешного решения задач транс- ляции. Кнут [87] провел экспериментальное исследование Фортран-программ В [58, 1131 при- ведены результаты анализа PL/1 и Паскаль программ. Производительность ряда трансляторов на различных системах команд обсуждается в [11. 58. 96]. Данная глава существенно использует материал книг [9. 23]. Многие из подходов к кодогене- рации, рассмотренные здесь, нашли свое применение в различных трансляторах. Фрейбургхаус [66] обсуждает использование счетчиков в качестве средства поддержки генерации хорошего кода для лучей Оптимальность стратегии, использованной в генрег для освобождения регист- ра путем удаления из регистра той переменной, использование которой отложено па более дальний срок, была доказана в [32] для задач подкачки страниц в память. Идея распределения фиксированного числа регистров для хранения переменных во время выполнения цикла была выдвинута в [98] и реализована для Фортрана Н в [95]. Методы распределения регистров на основе раскраски графов были предложены в [2]. Ход изложения вопросов раскраски графа в разд. 9 5 следует [45, 46] В [48, 49] описывается алго- ритм распределения регистров методами раскраски графа, основанной на приоритетах. Другие подходы к распределению регистров рассматриваются в [31, 35, 36, 39, 40, 48, 49, 55, 66, 79, 83, 85, 89, 101, 103, 105, 108—111, 115, 121, 122].
Гпава 9. Кодогенерация 727 Алгоритм разметки впервые был предложен А. П. Ершовым [10, 60] и применен в системе Альфа [2, 61]. Воплощающие этот метод алгоритмы кодогенерации рассматривались также в [28, 30, 100, 102, 106]. Работа [112] использовала указанный метод разметки в алгоритме, по- лучившем по имени авторов название алгоритма Сети-Ульмана, про который им удалось дока- зать оптимальность (по длине) сгенерированного кода для дерева выражений для широкого класса приложений. Процедура ГЕНКОД из разд. 9.6 является вариацией этого алгоритма, предложенной в [116]. В работе [16] предложена модификация алгоритма Сети-Ульмана, ис- пользующая минимальное число ячеек памяти; алгоритм при этом остается линейным. Работы [37, 55] содержат алгоритмы оптимальной кодогенерации для деревьев выражений, если объ- ектная машина имеет регистры, используемые в режиме стека. В работе [20] был предложен алгоритм динамического программирования, описанный в разд. 9.8. Он был использован в качестве основы в кодогенераторе переносимого Си- транслятора Джонсона, а также в трансляторе для ЭВМ IBM 370 Пиркена. Кнут [88] обобщил алгоритм динамического программирования на машины с асимметричными регистрами, таки- ми, как IBM 7090 и CDC 6600. При разработке этого обобщения Кнут рассмотрел кодогенера- цию как задачу разбора для контекстно-свободных грамматик. Флойд [63] предложил алгоритм для обработки общих подвыражений в арифметических вы- ражениях. Идея разбиения дэгов на деревья и раздельного использования для деревьев про- цедуры, подобной ГЕНКОД, рассматривалась в [119]. В [38, 111] была доказана УР-полнота задачи оптимальной кодогенерации для дэгов. В [21] было показано, что она остается NP- полной даже для машин с одним регистром и с неограниченным числом регистров (см. также [22]). Обсуждению влияния свойства Л'Р-полноты проблемы на возможность ее эффективного решения посвящена книга [8]. Преобразования на линейных участках изучались в работах [1, II, 25, 57]. Вопросы покадро- вой оптимизации и ее автоматизации рассматривались в [13, 52—54, 64, 65. 68, 72, 86, 91, 93, 99, 114]. В работе [118] рекомендуется использовать покадровую оптимизацию на уровне про- межуточного представления. Работы [94, 117] описывают методы для изменения локальных операторов передачи управления. В работах [43, 84] рассматривалась кодогенерация как процесс переписывания деревьев. Не- процедурному языку описания объектной машины и его использованию в качестве средства, облегчающего программирование генератора кода (точнее, алгоритма выбора команд), посвя- щены работы [17. 33, 34, 56]. В работах [18, 81] описаны алгоритмы сопоставления древовид- ному образцу и связь данной задачи с задачей кодогенерации. Рассмотренное в разд. 9.8 ком- бинирование эффективного сопоставления древовидного образца с динамическим программи- рованием предложено в работе [18]. В работах [18, 26, 28, 50, 73—78, 92, 104] описан и исследован подход к кодогенерации на ос- нове LR-анализатора для выбора команд. В [67, 69—71] рассматривается использование атри- бутных грамматик для спецификации и реализации кодогенераторов. Инструментам разработ- ки и отладки кодогенерации и других компонент транслирующих систем на основе формаль- ных описаний методами атрибутных грамматик посвящена книга [14]. Книга [15] является еще одной попыткой представить через единую "атрибутную" точку зрения на процесс разработки компилятора материал кодогенерации и всех других "классических" разделов конструирования трансляторов. Работа [19] посвящена системе Twig, основанной на схемах трансляции деревьев, рассмотрен- ных в разд. 9.9. Система BEG и методы, лежащие в основе ее работы, излагаются в работе [59]. В работе [3] предложена модификация алгоритма синтаксического анализа Кока-Янгера- Касами, ориентированная на использование при генерации кода, показано, что алгоритмы, используемые системами BEG и Twig, аналогичны указанной модификации алгоритма, и
728 Часть II. Применение графов и граф-моделей предложен метод, позволяющий совместить выделение общих подвыражений, оценку стоимо- сти выбираемых команд и распределение регистров. Другие методы автоматического конструирования кодогенераторов предлагались в работах [5. 6, 41—44. 47, 65. 80, 82, 90, 97, 102. 123]. Переносимость трансляторов также обсуждается в [Ю7]. Список литературы I. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции. М.: Мир, 1978, —Т. 1.2. 2. Бабецкий Г. И., Бежанова М. М. и др. АЛЬФА — система автоматизации программирова- ния.— Новосибирск: Наука, 1967. 3. Бездушный А. Н.. Серебряков В. А. Применение методов синтаксического анализа для ав- томатической генерации оптимального кода// Системная информатика. - Новосибирск: Наука, 1993. — Выпуск 3.—С. 130—164. 4. БирюковА. Н. Методы построения генераторов кота// Прикладная информатика.— М.: Финансы и статистика. 1987. — С. 173—208. 5. Грабарь А. В., Земцов П. А.. Налимов Е. В. Оптимизирующий генератор кода в проекте СОКРАТ // Интеллектуализация и качество программного обеспечения.— Новосибирск: ИСИ СО РАН, 1994. — С. 49—67. 6. Грабарь А. В., Земцов П. А., Налимов Е. В. Вопросы архитектурной настройки в оптими- зирующем генераторе кода проекта СОКРАТ // Проблемы конструирования эффективных и надежных программ. — Новосибирск: ИСИ СО РАН, 1995. — С. 93—104. 7. ГрисД. Конструирование компиляторов для цифровых вычислительных машин.— М.: Мир. 1975. 8. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые задачи. — М.: Мир, 1982. 9. Евстигнеев В. А., Касьянов В. Н. Теория графов. Алгоритмы обработки бесконтурных графов. — Новосибирск: Наука, 1998. 10. ЕршовА. П. О программировании арифметических выражений// Докл. АН СССР.— 1958. —Т. 118, №3. — С. 427—430. 11. Касьянов В. Н. Оптимизирующие преобразования программ. — М.: Наука, 1988. 12. Касьянов В. Н., Поттосин И. В. Методы построения трансляторов.— Новосибирск: Нау- ка, 1986. 13. Мавлютов И. Б. Подходы к щелевой оптимизации// Интеллектуализация и качество про- граммного обеспечения. — Новосибирск: ИСИ СО РАН. 1994. — С. 123—128. 14. Пактштас А., Золотарев Н. В. Синтаксически-орисптированныс компоненты распределен- ных систем. — М.: Наука, 1992. 15. Серебряков В. А. Лекции по конструированию компиляторов. — М.: ВЦ РАН, 1994. 16. Чеботарь К. С. Оптимальное использование рабочих ячеек в алгоритме Сети—Ульмана// Программирование. — 1983. —№ 3. 17. Черемисинов Д. И. Система для программирования блоков генерации команд// Програм- мирование. — 1982. — № 3. — С. 44—51.
Гпава 9. Кодогенерация 729 18. Aho А. V., Ganapathi М. Efficient tree pattern matching: an aid to code generation// Twelfth Annua) ACM Symposium on Principles on Principles of Programming Languages. — 1985. — P. 334—340. 19. Aho A. V., Ganapathi M., Tjiang S. W. Code generation using tree matching and dynamic pro- gramming// ACM Trans, on Programming Languages and Systems.— 1989.— Vol. 11, N4.— P 491 516 20. Aho A. V., Johnson S. C. Optimal code generation for expression trees // J. ACM. — 1976. — Vol. 23, N3.— P. 488 501. 21. Aho A. V., Johnson S C.. Ullman J. D. Code generation for expressions with common subex- pressions//J. ACM.- 1977. Vol. 24. N L — P. 146—160. 22. Aho A. V., Johnson S. C.. Ullman J. D. Code generation for machines with multiregister opera- tions // Fourth ACM Symp. on Principles of Programming Languages. -— 1977. — P. 21—28. 23. Aho A. V.. Johnson S. C., Ullman J. D. Compilers: principles, techniques and tools.—- N.Y.: Addison-Wesley, 1986. 24. Aho A. V., Sethi R. How hard is compiler code generation? // Lecture Notes in Computer Sci- ence. — Springer-Verlag. Berlin. 1977. —Vol. 52. -— P. 1 —15 25. Aho A. V.. Ullman J. D. Optimization of straight line code// SIAM J. Computing.— 1972. — Vol. 1,N 1 — P 1—19. 26. Aigrain P., Graham S. L., Henry R. R.. McKusick M. K, and Pelegri-Llopart E. Experience with a Graham-Glanville style code generator// ACM SIGPLAN Notices.— 1984 — Vol. 19, N6. — P. 13—24. 27. Ammann U. On code generation in a Pascal compiler// Software-Practice and Experience.— 1977, —Vol. 7, N 3. — P. 391—423. 28. Anderson J. P. A note some compiling algorithms // Comm. ACM. — 1964. — Vol. 7, N 3. — P. 149—150. 29. Auslander M. A., Hopkins M. E. An overview of the Pl.8 compiler// ACM SIGPLAN No- tices. — 1982. — Vol. 17. N 6 -P 22 31. 30. Beatty J. C. An axiomatic approach to code optimization for expressions // J. ACM. — 1972. — Vol. 19. N 4. — P. 714—724. Errata 20 (1973). P. 180 and 538. 31. Beatty J. C. Register assignment algorithm for generation of highly optimized object code// IBM J. Research and Development. — 1974. —Vol. 5. N 2. — P. 20—39. 32. Belady L. A. A study of replacement algorithms for a virtual storage computer// IBM Systems J. — 1966.— Vol. 5, N2. — P. 78—101. 33. Bird P. L. An implementation of a code generator specification language for table driven code generators // ACM SIGPLAN Not. — 1982. — Vol. 17, N 6. — P. 44—55. 34. Boulton P. 1. P., Goguen J. R. A machine description language// The Computer Journal.— Vo). 22, N 2. 35. Brian R. Nickerson. Graph coloring register allocation for processors with multi-register oper- ands // SIGPLAN Notices. — 1990. — Vol. 25. N 6. — P. 40—52. 36. Briggs P., Cooper K. D., Torczon L. Improvements to graph coloring register allocation // ACM Trans. Program Lang. Syst. 1994 — Vol. 16, N 3. — P. 428—455. 37. Bruno J., Lassagne T. The generation of optimal code for stack machines // J. ACM. — 1975. — Vol. 22, N3. — P. 382—396.
730 Часть II. Применение графов и граф-моделей 38. Bruno J., Sethi R. Code generation for a one-register machine // J. ACM. — 1976. — Vol. 23, N3.-P. 502—510. 39. Callahan D., Carr S., Kennedy K. Improving register allocation for subscripted variables // ACM SIGPLAN Notices. — 1990. — Vol. 25, N 6. — P. 53—65. 40. Callahan D., Koblenz B. Register allocation via hierarchical graph coloring // ACM SIGPLAN Notices. — 1991. — Vol. 26, N 6. — P. 192—203. 41. Carr M. Code generation by coagulation // ACM SIGPLAN Notices. — 1984 — Vol. 19, N 6. 42. Carter J. L. A Case study of a new code generation technique for compilers // Comm. ACM. — Vol. 20, N 12. 43. Cattel R. G. G. Automatic derivation of code generators from machine descriptions // ACM Trans. Program. Lang. Syst. — 1980. — Vol. 2, N 2. — P. 173—190. 44. Cattel R. G. G., Newcomer J. M., Leverett B. W. Code generation in a machine-independent compiler // ACM SIGPLAN Not. — 1978. — Vol. 14, N 8. 45. Chaitin G. J. Register allocation and spilling via graph coloring // ACM SIGPLAN Notices. — 1982. — Vol. 17, N 6. — P. 98—105. 46. Chaitin G. J., Auslander M. A., Chandra A. K., Cocke J., Hopkins M. E., Markstein P. W. Regis- ter allocation via coloring // Computer Languages. — 1981. — Vol. 6. — P. 47—57. 47. Chow F. C., Ganapathy M. Intermediate languages in compiler construction — a bibliography// ACM SIGPLAN Notices. — 1983. — Vol. 18, N 11. 48. Chow F. C., Hennessy J. L. Register allocation by priority-based coloring // ACM SIGPLAN Notices. — 1984. — Vol. 19, N 6. — P. 222—232. 49. Chow F. C., Hennessy J. L. The priority-based coloring approach to register allocation // ACM Trans. Program. Lang. Syst.. — 1990. — Vol. 12, N 4. — P. 501—536. 50. Christopher T. W., Hatcher P. J., Kukuk R. C. Using dynamic programming to generate optimal code in a Graham— Glanville style code generator// ACM SIGPLAN Notices.— 1984.— Vol. 19, N 6. 51. Coffman E. G., Jr., Sethi R. Instruction sets for evaluating arithmetic expressions // J. ACM. — 1983. — Vol. 30, N 3. — P. 457—478. 52. Davedson J. W., Fraser C. W. Automatic generation of peephole optimizations // ACM SIGPLAN Notices. — 1984. — Vol. 19, N 6, — P. 111—116. 53. Davidson J. W., Fraser C. W. Code selection through object code optimization // ACM Trans. Program. Lang. Syst. — 1984. — Vol. 6, N 4. — P. 505—526. 54. Davidson J. W., Fraser C. W. The design and application of a retargetable peephole optimizer// ASM Trans. Program. Lang. Syst. — 1980. — Vol. 2, N 2. — P. 191—202. Errata 3:1 (1981) 110. 55. Ditzel D., McLellan H. R. Register allocation for tree: the C machine stack cache // Proc. ACM Symp. on Architectural Support for Programming Languages and Operating Systems. — 1982, —P. 48—56. 56. Donegan M. K., Noonan R. E., Feycock S. A. Code generator language // ACM SIGPLAN No- tices. — 1979. — Vol. 14, N 8. 57. Downey P. J., Sethi R. Assignment commands with array references// J. ACM.— 1978.— Vol. 25, N 4. — P. 652—666. 58. Elshoff .1. L. An analysis of some commercial PL/1 programs // IEEE Trans Software Engineer- ing. — 1976. — Vol. SE2, N 2. — P. 113—120.
Гпава 9. Кодогенерация 731 59. Emmelmann Н., Schroer F.-W., Landwehr R. BEG — a generator for efficient back ends // ACM SIGPLAN Not. — Vol. 24, N 7. — 1989. — P. 227—237. 60. Ershov A. P. On programming of arithmetic operations// Comm. ACM.— 1958.— Vol. I, N 8. — P. 3—6. 61. Ershov A. P. The Alpha Automatic Programming System. — Academic Press: New York, 1971. 62. Eulf W. A., Johnsson R. K., Weinstock С. B., Hobbs S. O., Geschke С. M. The Design of an Optimizing Compiler. — American Elsevier. New York, 1975. 63. Floyd R. W. An algorithm for coding efficient arithmetic expressions // Comm. ACM. — 1961. —Vol. 4,N 1. —P. 42—51. 64. Fraser C. W. A compact, machine-independent peephole optimizer// Sixth Annual ACM Sym- posium on Principles of Programming Languages. — 1979. — P. 1—6. 65. Fraser C. W. A knowledge — based code generator generator // ACM SIGPLAN Notices. — 1977. —Vol. 12, N 8. 66. Freiburghouse R. A. Register allocation via usage counts // Comm. ACM. — 1974. — Vol. 17, N IL —P. 638—642. 67. Ganapathi M., Fischer C. N. Description-driven code generation using attribute grammars// Ninth ACM Symposium on Principles of Programming Languages. — 1982. — P. 108—119. 68. Ganapathi M., Fischer C. N. Integrating code generation and peephole optimization // Acta In- formatica. — 1988. — Vol. 25. — P. 84—109. 69. Ganapathi M., Fischer C. N.. Hennessy J. L. Retargetable compiler code generation // Comput- ing Surveys. — 1982. — Vol. 14, N 4. — P. 573—592. 70. Ganapathy M., Fischer C. N. Affix grammars driven code generation // ACM Trans, on Princi- ples of Programming Languages. — 1985. — Vol. 7, N 4. 71. Ganapathy M., Fischer C. N. Attributed linear intermediate representations for retargetable code generators // Software-Practice and Experience. — 1984. — Vol. 14, N 4. 72. Giegerich R. A formal framework for the derivation of machine specific optimizers // ACM Trans. Program. Lang. Syst. — 1983. — Vol. 5, N 3. — P. 422—448. 73. Glanville R. S., Graham S. L. A new method for compiler code generation // Fifth ACM Sympo- sium on Principles of Programming Languages. — 1978. — P. 231—240. 74. Graham S. L. Code generation and optimization // Methods and tools for compiler construc- tion. — Cambridge Univ. Press, 1984. — P. 251—288. 75. Graham S. L. Table-driven code generation // Computer. — 1980. — Vol. 13, N 8. — P. 25— 34. 76. Graham S. L., Glanville R. S. The use of a machine description for compiler code generation // Third Jerusalem Conf, on Information Technology. —North-Holland, 1978. 77. Graham S. L., Henry R. R., Schulman R. A. An experiment in table driven code generation // ACM SIGPLAN Notices. — 1982. — Vol. 17, N 6. — P. 32—43. 78. Grawford J. Engineering a production code generator// ACM SIGPLAN Notices.— 1982.— Vol. 17, N6. — P. 205—215. 79. Gupta R., Soffa M. L., Ombres D. Efficient register allocation via coloring using clique separa- tors // ACM Trans. Program. Lang. Syst. — 1994. — Vol. 16, N 3. — P. 370—386. 80. Hennessy .1. L., Gross T. R. Code generation and reorganization in the presence of pipeline con- straints //Ninth ACM Symp. on Principles of Programming Languages. — 1982.
732 Часть II. Применение графов и граф-моделей 81. Hoffman С. М. O'Donnell М. J. Pattern matching in trees// J. ACM.— 1982.— Vol. 29, N 1, —P. 68—95. 82. Horspool R. N., Scheunemann A. Automating the selection of code templates // Software — Practice and Experience. — 198^ — Vol. 15, N 5. 83. Horwitz L. P., Karp R. M., Miller R. E., Winograd S. Index register allocation // J. ACM. — 1966. —Vol. 13, N 1. —P. 43—61. 84. Johnson S. C. A portable compiler: theory and practice // Fifth Annual ACM Symposium on Principles of Programming Languages. — 1978. — P. 97—104. 85. Kennedy K. Index register allocation in straight line code and simple loops // Design and Opti- mization of Compilers. — Prentic-Hall, Englewood Cliffs, 1972. — P. 51—64. 86. Kessler R. R. Peep— an architectural description driven peephole optimizer// ACM SIGPLAN Notices.—1984, —Vol. 19, N 6, — P. 106—110. 87. Knuth D. E. An experimental study of FORTRAN programs // Software — Practice and Experience.— 1981. — Vol. 1,N2. — P. 105—113. 88. Knuth D. E. A generalization of Dijkstra's algorithm // Information Processing Letters. — 1977. —Vol. 6. —P. 1—5. 89. Kolte P., Harrold M. J. Load/Store Range Analysis for Global Register Allocation // ACM SIGPLAN Notices. — 1993. — Vol. 28, N 6. — P. 268—277. 90. Krumme D. W., Ackley D. H. A practical method for code generation based on exhaustive search//ACM SIGPLAN Notices. — 1982, —Vol. 17,N6. — P. 185—196. 91. Lamb D. A. Construction of a peephole optimizer// Software— Practice and Experience.— 1981. — Vol. 11. — P. 638—647. 92. Landwehr R., Jansohn H.-S., Goos G. Experience with an Automatic Code Generator // ACM SIGPLAN Notices. — 1982.— Vol. 17, N6. — P. 56—66. 93. Leverett B. W., Cattell R. G. G., Hobbs S. O., Newcomer J. M., Reiner A. H., Schatz B. R., Wulf W. A. An overview of the production-quality compiler-compiler project // Computer. — 1980. — Vol. 13, N 8. — P. 38—40. 94. Leverett B. W., Szymanski T. G. Chaining span-dependent jump instructions // ACM Trans. Program. Lang. Syst. — 1980. — Vol. 2, N 3. — P. 274—289. 95. Lowry E. S., Nedlock C. W. Object code optimization // Comm. ACM. — 1969. — Vol. 12. — P. 13—22. 96. Lunde A. Empirical evaluation of some features of instruction set processor architectures // Comm. ACM. — 1977. — Vol. 20, N 3. — P. 143—153. 97. Madhavan M., Shankar P., Rai S., Ramakrishna U. Extending Graham-Glanville techniques for optimal code generation // ACM Trans, on Programming Languages and Systems. — 2000. — Vol. 22, N 6. — P. 973—1001. 98. Marill T. Computational chains and the simplification of computer programs // IEEE Trans. Electronic Computers. — 1962. — Vol. EC-11, N 2. — P. 173—180. 99. McKeeman W. M. Peephole optimization// Comm. ACM.— 1965.— Vol. 8, N 7.— P. 443—444. 100. Nakata I. On compiling algorithms for arithmetic expressions// Comm. ACM.— 1967.— Vol. 10, N 8. — P. 492—494.
Гпава 9. Кодогенерация 733 101. Nickerson В. R. Graph coloring register allocation for processors with multiregister operands // ACM SIGPLAN Notices. — 1990. — Vol. 25, N 6. — P. 40—52. 102. Nievergelt J. On the automatic simplification of computer code// Comm. ACM.— 1965.— Vol. 8, N 6. — P. 366—370. 103. Norris C., Pollock L. L. Register allocation over the program dependence graph // ACM SIGPLAN Notices. — 1994. — Vol. 29. N 6. — P. 266—277. 104. Oh S. M., Park J. C. A note on removing loops from table-driven code generators // Information Processing Letters. — Vol. 21, N 1. — P. 31—34. 105. Proebsting T. A., Fischer C. N. Probalistic register allocation// ACM SIGPLAN Notices.— 1992. — Vol. 27, N 7. — P. 300—310. 106. Redziejowski R. R. On arithmetic expressions and trees // Comm. ACM. — 1969. — Vol. 12, N2. —P. 81—84. 107. Richards M. The portability of the BCPL compiler// Software— Practice and Experience. — 1971—Vol. 1,N2_ —P. 149—157. 108. Ripken K. A formal method for describing machine code generation with local optimizations // Le point sur la compilation. — Montpellier: 1R1A. 1978. 109. Rustin N. Design and Optimization of Compilers.— Prentic-Hall, Englewood Cliffs, NJ., 1972. 110. Santhanam V., Odnert D. Register allocation across procedure and module boundaries // ACM SIGPLAN Notices. — 1990. — Vol. 25. N 6. — P. 28—39. 111. Sethi R. Complete register allocation problems// SIAM J. Computing.— 1975.— Vol. 4, N 3. — P. 226—248. 112. Sethi R., Ullman J. D. The generation of optimal code for arithmetic expressions // .1. ACM. — 1970. — Vol. 17, N 4. — P. 715—728. 113. Shimasaki M., Fukaya S., Ikeda K., Kiyono T. An analysis of Pascal programs in compiler writing//Software — Practice and Experience.— 1980. — Vol. 10, N 2. — P. 149—157. 114. Snyder L. Recognition and selection of idioms for code optimization// Acta Informatica.— 1982. — Vol. 17. — P. 327—345. 115. Steenkiste P. A., Hennessy .1. L. A simple intcrprocedural register allocation algorithm and its effectiveness for Lisp// ACM Trans. Program. Lang. Syst.— 1989.— Vol. 11, N 1.— P. 1—32. 116. Stockhausen P. F. Adapting optimal code generation for arithmetic expressions to the instruc- tion sets available on present-day computers// Comm. ACM.— 1973.— Vol. 16. N 6.— P. 353—354. Errata. — Vol. 17, N 10. — 1974. — P. 591. 117. Szymanski T. G. Assembling code for machines with spandependent instructions// Comm. ACM. — 1978. — Vol. 21, N 4. — P. 300—308. 118. Tanenbaum A. S., Staveren H. V., Stevenson .1. W. Using peephole optimization on intermedi- ate code // ACM Trans. Program. Lang. Syst. — 1982. — Vol. 4, N 1. — P. 21—36. 119. Waite W. M. Code generation // Lecture Notes in Computer Science. — 1976. — Vol. 21. — P. 302—332. 120. Waite W. M. Optimization// Lecture Notes in Computer Science.— 1976.— Vol. 21.— P. 549—602.
734 Часть II. Применение графов и граф-моделей 121. Wall D. W. Register allocation at link time// ACM SIGPLAN Notices. — 1986. — Vol. 21, N 7. — P. 264—275 122. Wall D. W. Register windows versus register allocation// ACM SIGPLAN Notices.— 1988. — Vol. 23, N 7. — P. 67—78. 123. Wand M Deriving target code as a representation of continuation semantics // ACM Trans, on Programming Languages and Systems. — 1982. — Vol. 4, N 3. — P. 496—517. 124. Wulf W. A., Johnsson R. K., Weinstock С. B., Hobbs S. O., Ceschke С. M. The Design of an Optimization Compiler. —N.Y.: American Elsevier, 1975.
ГЛАВА 1 О Потоковый анализ программ Потоковый анализ является средством получения достоверной информации в поведе- нии программы без ее реального исполнения. Извлекаемые из текста программы свойства — это глобальная информация о программе, которая не может быть получе- на ни пробными запусками программы, ни изучением ее отдельных фрагментов. Ос- новной задачей потокового анализа является схематизация оптимизируемой про- граммы — построение по программе моделирующей ее схемы, в которой важные для оптимизации свойства программы представлены с достаточной степенью точности. В процессе потокового анализа происходит извлечение определенных (схемных) се- мантических свойств программы; при этом используются семантика языка и текст анализируемой программы. Однако, в отличие от "доказателей теорем" о программах, потоковый анализ использует далеко не полную семантику языка и выводит сущест- венно более простые свойства программы, чем свойство правильности или свойство пустоты. Техника потокового анализа— это "метод транзитивного замыкания", за- метно уступающий по мощности таким общим методам доказательства теорем, как, например, "метод резолюций", но приводящий к существенно более эффективным алгоритмам. Алгоритмы потокового анализа воспринимают программу (процедуру, модуль, про- граммную систему и т. д.) в качестве входных данных, выявляют статическую ин- формацию (вид которой! зависит от конкретной решаемой проблемы) и возвращают полученную информацию в качестве результата Такие алгоритмы используются при решении задач оптимизации, верификации, отладки, тестирования, распараллелива- ния, векторизации, параллельного программирования и во многих других приложе- ниях. Они обеспечивают нахождение информации о программе или среде (окруже- нии) без исполнения кода. Глава начинается с рассмотрения задачи анализа потока управления. Рассматривают- ся методы и алгоритмы анализа гамачной структуры программы и выявления отно- шений обязательного предшествования, играющих существенную роль в различных приложениях. Исследуются вопросы анализа структурной сложности программ. Опи- сываются модели и методы анализа потока данных в программе.
736 Часть II. Применение графов и граф-моделей 10.1. Анализ потока управления Традиционно потоковый анализ разделяют на анализ потока управления и анализ по- тока данных. Основной задачей анализа потока управления является представление и структуризация множеств исполнений программы, а также нахождение свойств опе- раторов и переходов в этих исполнениях и выбор порядка обработки операторов про- граммы. Все эти задачи могут иметь самостоятельное значение, большинство из них возникает из нужд анализа потока данных, который, как правило, следует за анализом потока управления. 10.1.1. Представление множеств исполнений При оптимизации имеют дело не с детальным описанием программы, а с ее упрощен- ной моделью — схемой программы, в которой такие понятия, как оператор, перемен- ная, процедура, выполнение и т. д., являются обобщением соответствующих понятий существующих языков программирования. Схема программы моделирует целый класс конкретных программ, имеющих одинаковую информационно-логическую структуру, т. е. описывает их таким образом, что множество преобразований, кор- ректных для схемы, образуется из преобразований, корректных для всех моделируе- мых ею программ. При переходе от программы к моделирующей ее схеме игнориру- ются несущественные особенности (например, синтаксические) корректного языка программирования и сохраняются только те (семантические) свойства программы, которые используются для проведения оптимизирующих преобразований. В схеме программы сохраняется часть структурных свойств программы; например, как правило, в схеме отражается членение программы на операторы, а памяти про- граммы на переменные. Однако конкретные объекты программы (константы, опера- ции и переменные) в схеме программы заменены абстрактными символами, каждый из которых представляет некоторый класс конкретных объектов соответствующего вида, допустимых в качестве интерпретации этого символа. Поэтому в отличие от оператора программы, задающего некоторую функцию над данными, оператор в схе- ме описывает класс функций, соответствующих различным допустимым интерпре- тациям формальных символов. Например, оператор присваивания х := (х + 5) *у в схеме может иметь вид х :=/(g(x, /?), у), где/и g — символы любых бинарных опе- раций, ah — символ 0-арной операции (или константы). В большинстве случаев ар- ность операций, а также фиксация определенных алгебраических законов (например, можно зафиксировать, что f— это символ коммутативной бинарной операции) явля- ются единственными ограничениями на класс допустимых интерпретаций формаль- ных символов, используемых в схемах. Как и в программе, оператор в схеме может иметь некоторое множество операндов', одни из них являются (информационными) входами, а другие — (информационными) выходами. Идентификация взаимовлияний операторов и элементов памяти осуществ- ляется указанием переменных, соответствующих каждому операнду оператора. Пе- ременные, соответствующие входам оператора, называются его аргументами, а вы- ходам — результатами. Если оператор в схеме имеет не более одного преемника по
Глава 10. Потоковый анализ программ 737 управлению, то он преобразователь, иначе (когда оператор служит не только для преобразования информации, но и осуществляет выбор преемника для выполнения) он называется распознавателем. Внутренняя структура оператора может ограничивать возможности взаимодействия оператора с памятью: некоторые операнды должны работать с разными переменными (информационная несовместимость), а другие— отождествляться по памяти (ин- формационная связность). Например, одно и то же действие выражают операторы х :=х + 1 и х + := 1, каждый из которых содержит два операнда: вход и выход; струк- тура первого оператора не запрещает в качестве аргумента взять другую переменную (например, переменную у, если х = у), а во втором операторе операнды являются ин- формационно связанными. По два информационно несовместимых выхода и по два информационно связанных входа имеют операторы если у > 2 то z := 1; х := у все и если у> 2 то х := у; z := 1 все, причем в первом операторе выход, которому сопос- тавлена переменная z, информационно несовместим со входами оператора, а во вто- ром операторе соответствующий выход и входы можно отождествлять по памяти. Между операторами программы существует два типа отношений, реализуемых в вы- полнениях программы: связь по передаче управления—управляющая связь, когда один оператор выполняется непосредственно вслед за другим; связь по передаче ин- формации — информационная связь, когда оператор при своем исполнении по одно- му из входов использует информационное значение, выработанное в результате рабо- ты другого оператора по одному из его выходов. Поток управления (система управляющих связей) в схеме обычно задается явно в виде так называемого управляющего графа (уграфа)— см. разд. 4.1.1. Это ориенти- рованный граф, вершинами которого являются операторы, а дуги соединяют любую пару операторов, между которыми возможна передача управления. Таким образом, каждому выполнению схемы (а следовательно, и программы с этой схемой) соответ- ствует некоторый путь по уграфу от начальной вершины уграфа (или, что то же са- мое, начального оператора схемы). Это выполнение либо конечно, когда оно достига- ет одной из конечных вершин уграфа, либо бесконечно. Указанный путь для кратко- сти будем называть также путем по схеме. Вершинами информационного графа, используемого для представления потока дан- ных (системы информационных связей), являются операнды операторов, а дуги со- единяют все такие выходы а и Ь, что между оператором с выходом а и оператором с входом b существует информационная связь через операнды а и Ь. Построение системы графов, кодирующих достаточно точно последовательности вы- полнений операторов внутри процедур и межпроцедурные переходы, является срав- нительно простой задачей для языков типа Фортран и может быть выполнено на ос- нове семантики операторов языка до выполнения анализа потока данных. Эта задача усложняется для языков типа Алгол-60 (из-за формальных меток и процедур) и ста- новится особенно сложной для языков типа ПЛ/1 или Алгол-68, которые содержат указатели, а также переменные метки и процедуры. В этом случае задачи более точ- ного определения управляющих и информационных связей оказываются тесно взаи- мосвязанными (см. разд. 11.3.8). 24 Зак. 202
738 Часть II. Применение графов и граф-моделей Основной моделью программ, в рамках которой решаются задачи анализа потока управления в программе, являются схемы Мартынюка. В крупноблочной схеме тако- го типа отсутствует информация о структуре памяти моделируемой программы и о внутренней структуре операторов; в ней сохраняется только членение программы на операторы, а также информация о тождественности операторов и управляющих связях между операторами. Пусть имеется алфавит символов операторов L, состоящий из символов преобразова- телей и ^-распознавателей, где к > 1. Тогда схему Мартынюка (см. разд. 11.3.3) можно представить как пару a = (G, L) Здесь G— управляющий граф (уграф) схемы — упорядоченный мультиграф с выде- ленными начальной вершиной ро и непустым множеством конечных вершин Q, a L — разметка, сопоставляющая каждой невыделенной вершине р оператор L(p) из Е таким образом, что Цр) является преобразователем, если из р не исходит больше одной ду- ги, и ^-распознавателем, если из р исходит к дуг, где к > 1. Схема а называется правильной, если каждая ее вершина принадлежит хотя бы одно- му пути от ее начальной вершины до конечной. Схема cti является правильной частью схемы а2, если может быть получена из а2 удалением всех вершин, не принадлежащих путям по а2 от ее начальной вершины до конечной. Если Р— некоторый путь (рь иь р2,..., w,._H р,.) по схеме а, то L(p') обозначает слово £(pj)£(p2)... £(рг) из Е*. Пусть Pi = (pi, щ, Pi, —, ur-i, Pt) и Pi = (9i, vi> 92, —, vr-i, — пути по схемам cq и a2 соответственно. Говорят, что Pt и P2 согласуются, если Li(P() = £2(Р2) и для любого) дуга iij является /-й исходящей дугой тогда и только тогда, когда дуга v; является i-й исходящей дугой. А. Две схемы Мартынюка эквивалентны как крупноблочные схемы тогда и только тогда, когда для каждого пути, соединяющего начальную вершину с конечной в од- ной схеме, существует согласованный с ним путь в другой схеме. На рис. 10.1 приведены две эквивалентные схемы Мартынюка, в которых дуги, исхо- дящие из одной вершины, упорядочены против часовой стрелки, а первая дуга изо- бражена двойной линией. Рис. 10.1. Эквивалентные схемы Мартынюка
Глава 10. Потоковый анализ программ 739 Б. Если схемы эквивалентны, то правильные их части также эквивалентны. В. Если две вершины правильных эквивалентных схем, в одной из которых пометки всех вершин попарно различны, помечены одним и тем же символом, то для любого пути, исходящего из одной из этих вершин, существует согласованный с ним путь, исходящий из другой вершины. Г. Две такие правильные схемы, что в одной из них пометки всех вершин попарно различны, эквивалентны тогда и только тогда, когда в схемах совпадают множе- ства пометок и из любых двух вершин, одинаково помеченных, исходит равное число дуг, причем соответствующие (по порядку) дуги заходят в одинаково помеченные вершины. Обычно (если это не будет оговорено особо) мы будем рассматривать правильные схемы Мартынюка, в которых уграф не содержит кратных дуг, пометки всех вершин попарно различны, а множество конечных вершин Q состоит из единственной вер- шины, обозначаемой через q0. Поэтому под схемой (Мартынюка) мы обычно будем понимать уграф G = (A', U) с двумя выделенными вершинами: начальной р0 и конеч- ной q0, любая вершина которого принадлежит хотя бы одному пути по G от началь- ной вершины до конечной, и считать, что две схемы G! и G2 эквивалентны, если гра- фы G] и G2 изоморфны. Через п будем обозначать количество вершин схемы G, а че- рез т — количество ее дуг. Д. В схеме G число вершин п не превышает т + 1. В общем случае схема программы представляет собой совокупность схем процедур, среди которых выделена так называемая главная (ведущая) процедура. Эти схемы процедур кодируют только внутрипроцедурные последовательности выполнений операторов. Что же касается межпроцедурных связей, то возможные последователь- ности исполнений операторов вызова, реализующих цепочки вложенных обращений одних процедур к другим (включая рекурсивные обращения, т. е. обращения про- цедуры к самой себе), обычно задаются в виде таких конструкций, как графы про- цедур, вызовов и зацепленности. Граф процедур — это ориентированный граф, вершинами которого являются про- цедуры, а дуги отражают возможность прямого обращения из одной процедуры к другой. При этом предполагается, что все исполнения операторов вызова, обращаю- щихся к одной и той же процедуре, приводят к одним и тем же цепочкам вложенных вызовов процедур. Для более точного кодирования межпроцедурных связей исполь- зуется граф вызовов, вершинами которого являются операторы вызова, а дуги отра- жают непосредственную вложенность вызовов. В этом графе склеены, однако, все выполнения так называемых особых вызовов — таких, при разных выполнениях ко- торых могут вызываться разные процедуры (такая ситуация, например, часто имеет место в языках, допускающих операторы вызова процедур, являющихся формальны- ми параметрами). Выполнения особых вызовов расклеиваются в графе зацепленно- сти, вершинами которого являются пары оператор вызова — вызываемая процедура, а дуги отражают непосредственную вложенность соответствующих пар. Выбор того или иного графа для представления межпроцедурных переходов осуще- ствляется в зависимости от требований к точности их представления и от наличия или
740 Часть II. Применение графов и граф-моделей отсутствия в моделируемой программе рекурсивных процедур, а также переменных и формальных процедур (рис. 10.2). program Р; procedure F(f,g); begin ... 4: f(g);... end; procedure Q(h,t)\ begin ... 5 : h(t);... end; procedure Л/fs); begin ... 6 : s(R,S):... end; procedure; M(r): begin ... 7: r(R.S):... end; begin ... 2: F(N,Q);... 3 : Q(M.F); ...end. Граф процедур Рис. 10.2. Разные способы представления межпроцедурных связей в программе 10.1.2. Структуризация Важной стороной анализа потока управления является представление программы в виде иерархии фрагментов специального вида (лучей, гамаков, зон и т. д.). Иногда в процессе анализа для получения определенных свойств программы (как правило, регулярности ее структуры) осуществляются специальные эквивалентные преобразо- вания. В языках программирования обычно имеется возможность написания иерархических операторных конструкций. Например, группа операторов может объединяться в такие конструкции более сложного вида, как составной оператор, оператор выбора или оператор цикла. Обобщением соответствующих понятий в схемах программ являются такие типы фрагментов схем, как луч, гамак и зона (фрагмент— это обобщенный оператор, и для него естественным образом вводятся понятия обязательных и необя- зательных аргументов и результатов). Определения этих фрагментов приведены в разд. 4.1. Многие задачи создания и обработки программ значительно упрощаются, если про- граммы имеют регулярную структуру, допускают представление в виде иерархий вложенных фрагментов специального вида. Например, структурное программирова- ние в качестве базовых рассматривает разные типы композиции операторов, но все они порождают только интервалы. Разрешив брать в качестве базовых любые интер- валы, получаем класс регуляризуемых или интервально сводимых схем (см. гл. 4).
Глава 10. Потоковый анализ программ 741 Важным свойством этого подкласса схем Мартынюка является существование алго- ритма преобразования любой схемы Мартынюка в эквивалентную ей интервально сводимую схему. 10.1.3. Нахождение свойств операторов и переходов Одним из основных видов информации, собираемой при анализе множеств исполне- ний программы, является информация о частоте выполнения групп операторов и пе- реходов. Информация этого типа является составной частью контекстных условий большинства оптимизаций. Одним из наиболее эффективных способов сокращения времени работы программы является перемещение оператора на участки программы с меньшей частотой выполнения. Частичную информацию о частоте выполнения мы получаем, рассматривая фрагменты программы; например, все операторы линейного участка выполняются одинаково часто. Изучая поток управления в программе, можно найти так называемые достоверные соотношения частот выполнения, т. е. соотно- шения, выполняющиеся в любом исполнении программы (эти соотношения важны почти для всех оптимизаций), либо рассматривать частоту выполнения операторов и переходов одновременно во всем множестве исполнений программы (что важно при решении задач сегментации). Отношения обязательного предшествования и обяза- тельной преемственности довольно просты для обнаружения и кодируют достовер- ные отношения частоты выполнения групп операторов и переходов, принадлежащих одним и тем же зонам, и поэтому широко используются на практике. Результаты опе- раторов (и фрагментов) в схеме часто полезно разделять на обязательные и необяза- тельные. Переменная является обязательным результатом некоторого оператора только в том случае, если каждое выполнение этого оператора в программе (соответ- ственно в схеме) обязательно задает значения всем компонентам данной переменной. Например, в операторе если z> 0 то z z + 2 все; у := 1; х[А] := z переменные х и z не являются обязательными результатами, а переменная у является. Если в схеме все результаты операторов необязательные, то наличие пути по схеме от оператора St с результатом х к оператору S2 с аргументом х говорит о возможности передачи информации от S) к S2 через переменную х при каком-то исполнении одной из моделируемых схемой программ. С другой стороны, если любой такой путь от S| к 5’2 проходит через оператор, у которого х— обязательный результат, то это гаран- тирует отсутствие информационной связи между операторами .8) и S2 через перемен- ную х в любой интерпретируемой программе. В том случае, когда все результаты операторов в программе являются обязательны- ми, имеется возможность моделирования ее в виде так называемой схемы над рас- пределенной памятью, упрощающей многие оптимизирующие преобразования, В отличие от общей памяти, когда переменные однозначно сопоставляются операн- дам операторов и одна и та же переменная может являться как аргументом, так и ре- зультатом нескольких операторов, при распределенной памяти переменные взаимно однозначно сопоставляются входам операторов, а значение, выработанное на выходе
742 Часть II. Применение графов и граф-моделей оператора, рассылается не в одну, а в несколько переменных. Другими словами, в схемах над общей памятью элементы памяти равнодоступны в том смысле, что опе- ратор, засылая значение в переменную, не "интересуется", где это значение будет использовано, а обращаясь за значением переменной, не "интересуется", откуда это значение поступило. В схемах же над распределенной памятью информационный граф задан явно, и оператор, вырабатывая результат, "знает", для каких операторов он предназначен, а воспринимая результат, "знает", какой оператор его подготовил. Переменная называется аргументом оператора (или фрагмента), если при некотором выполнении оператор читает из данной переменной значение, присвоенное ей други- ми выполнениями операторов. Для ряда оптимизирующих преобразований оказывается полезной информация о вли- янии значений тех или иных аргументов оператора на его выполнимость. Аргумента оператора называется необязательным, если оператор на любом множестве всех на- боров значений аргументов, различающихся только значениями переменной х, либо всегда нормально завершает свое выполнение, либо всегда приводит к аварийному завершению. Для обязательного аргумента х существуют два таких выполнения оператора, наборы значений аргументов которых различаются только значениями переменной х, что одно из выполнений оператора нормально завершается, а дру- гое — нет. Например, для каждого из операторов у := z /х и _у[х] :== г, принадлежащих синтаксически правильной программе на языке Паскаль, переменная х является обя- зательным аргументом, а переменная z— необязательным аргументом. Информационные объекты, обрабатываемые программой, как правило, связаны оп- ределенными отношениями, информация о которых может использоваться при опти- мизации программ. Например, значение элемента массива (или поля записи) всегда является частью значения всего массива (или всей записи). Другой пример — это оп- ределенное соотношение между значениями переменных, выполняющееся в некото- рой точке программы при любом ее исполнении, в частности равенство значения переменной одной и той же константе (такие соотношения называются инвариант- ными). Конструкция, предназначенная для кодирования в схеме бинарных отношений, суще- ствующих между информационными объектами во всем классе моделируемых схе- мой программ, получила название граф косвенной адресации (/64-граф). В этом графе для каждого кодируемого отношения существует свой тип дуг, которые в зависимо- сти от конкретной оптимизации представляют либо пересечение, либо объединение соответствующих отношений в каждой из программ, моделируемых схемой. Граф может сопоставляться всей схеме программы целиком, если все отношения статиче- ские (т. е. не меняются в процессе исполнения программы), или некоторым ее эле- ментам, если отношения динамические. 10.1.4. Выбор порядка обработки операторов Большая группа алгоритмов обработки программы требует расположения (укладки) операторов программы (возможно, с повторениями) в виде последовательности, оп- ределенным образом соответствующей исполнениям программы. Например, с точки
Глава 10. Потоковый анализ программ 743 зрения ряда оптимизаций оказывается полезным аранжировка программы (см. разд. 4.1.9)— такая ее укладка без повторения, порядок операторов в которой не противоречит их порядку в каждом исполнении программы, не содержащем повтор- ных исполнений операторов. В процессе выполнения алгоритмов оптимизации операторы оптимизируемой про- граммы (вершины схемы программы) обрабатываются в некоторой последовательно- сти, определенным образом соответствующей исполнениям программы. Например, для ряда алгоритмов анализа потока данных эта последовательность (укладка с по- вторением) должна содержать в качестве подпоследовательностей все или почти все простые пути по схеме программы, т. е. являться сильной или слабой укладкой (см. разд. 4.4.1). В основе большинства порядков обработки вершин схемы, реализуемых при потоко- вом анализе, содержатся так называемые прямая .и обратная нумерации вершин схе- мы. Эти базисные нумерации тесно связаны с поиском в глубину (возвратным ходом) по уграфу (см. разд. 2.2). Поиск в глубину начинается и заканчивается просмотром начальной вершины, а просмотр некоторой вершины задает переход от просматри- ваемой вершины к одному из ее непросмотренных преемников, если такие есть, или к тому ее предшественнику, который вызвал ее просмотр, в противном случае. Прямая нумерация отражает порядок, в котором при поиске в глубину вершины схемы пер- вый раз просматривались, а обратная нумерация — порядок, обратный порядку воз- вратов из вершин. Прямой нумерацией схемы G называется любая такая нумерация М ее уграфа, для которой справедливы следующие три свойства: □ Л/(ро) = 1; □ в любую вершину, отличную от рй, заходит хотя бы одна Л/-прямая дуга; □ если (р, q) — такая Л/-прямая дуга, что среди вершин с Л/-номерами из (M(p)'.M(q)) нет предшественников вершины q, то среди этих вершин нет и предшественников ни одной вершины, номер которой больше M(q). Возможная прямая нумерация схемы изображена на рис. 10.3, а. Если не оговорено особо, в качестве обозначений вершин изображаемой на рисунке схемы мы использу- ем их Л/-номера. Нумерация N схемы G называется ее обратной нумерацией, если существует такая прямая нумерация М схемы G, что для любых двух вершин схемы р и q неравенство N(p)<N(q) выполняется тогда и только тогда, когда либо вершина q является ^f-достижимой из вершины р, либо М(р) < M(q) и вершина р не является М- достижимой из вершины q. Для схемы G, изображенной на рис. 10.3, а, зафиксированная прямая нумерация схе- мы определяет такую ее обратную нумерацию, которая сопоставляет вершинам схе- мы номера, изображенные на рис. 10.3, б рядом с соответствующими им вершинами. Нетрудно увидеть, что одна и та же схема может иметь несколько разных прямых и обратных нумераций, а одна и та же обратная нумерация схемы может соответство-
744 Часть II. Применение графов и граф-моделей вать нескольким прямым нумерациям, что иллюстрируется схемой, изображенной на рис. 10.4. Рис. 10.3. Базисные нумерации схемы: а — прямая нумерация, б— прямая и обратная нумерации Алгоритм 10.1. Построение базисных нумераций Дано. Схема G. Требуется. Базисные нумерации N нМ схемы G. Метод. проц ВОЗВРАТНЫЙ-ХОД = 1. ПУТЬ: стек = {р0}; N: нумерация = {(р, £2): р X};
Глава 10. Потоковый анализ программ 745 2. М: нумерация = {(р, Й): р /- ро} о {(ро, 1)}; 3 Л/Л/ := n, NM := 2, 4. пока ПУТЬ # 0 цикл 5 q := э ПУТЬ, 6. если ПРЕЕМ(д) = 0то Л/(д) := Л/Л/; NM := NM- 1; Э ПУТЬ 7 иначе v = Э ПРЕЕМ(д); 8. если М(V) = О то ПУТЬ <- v; M(v) := NM: NM := NM + 1 все все все все А. Каждая схема G имеет ио крайней мере одну пару связанных базисных нуме- раций. Б. Прямая и обратная нумерации схемы являются правильными. В. Любая пара связанных базисных нумераций схемы G может быть получена с по- мощью алгоритма 10.1 за время О(т) В каждый момент выполнения алгоритма 10.1 стек ПУТЬ хранит некоторый простой путь по схеме G от ее начальной вершины. Пусть И7 обозначает множество всех таких дуг (р, q) схемы G, что в некоторый момент работы алгоритма дуга (р, q) принадле- жит простому пути, хранимому в стеке ПУТЬ. Г. Граф D = (X И7) является деревом с корнем р<у Дерево D называют остовным деревом для G, построенным поиском в глубину (или, короче, глубинным остовным деревом для G). Все множество дуг схемы G разбива- ется выполнением алгоритма 10.1 на четыре класса (относительно дерева D): древес- ные— дуги, принадлежащие дереву D; обратные— дуги, идущие от потомков к предкам (возможно, из вершины в себя); прямые — дуги, идущие от предков к по- томкам, но не являющиеся древесными или обратными; поперечные— дуги, соеди- няющие вершины, которые не являются ни предками, ни потомками одна другой. Глубинное остовное дерево для схемы G показано на рис. 10.5. Здесь древесные дуги нарисованы сплошными двойными линиями, обратные дуги — волнистыми линиями, поперечные дуги— штриховыми линиями, а прямые— сплошными ординарными линиями. Очевидные изменения алгоритма 10.1 позволяют ему за время О(т) не только стро- ить базисные нумерации, но и разделять дуги схемы на древесные, прямые, попереч- ные и обратные дуги. проц ГЛУБИННОЕ-ОСТОВНОЕ-ДЕРЕВО = 1. ПУТЬ: стек = {р0}: N: нумерация = {(р,й): реХ) 2. М. нумерация = {(р, й): р^рс}о{(р0, 1)}; 3. NN := л; NM := 2; 4. пока ПУТЬ * 0 цикл
746 Часть II. Применение графов и граф-моделей 5. q := эПУТЬ; 6. если HPEEM(q) = 0то N(q) := WW; NN := NN- 1; Э ПУТЬ 7. иначе v := ПРЕЕМ(д); 8. если M(v) = fl то (q, v) — древесная дуга; 9. М(у) := NM; NM - NM + 1; 10. иначе если M(q) < M(v) то (q,v) — прямая дуга 11. иначе если 7V(v) = П то (q,v) — обратная дуга 12. иначе (q, v) — поперечная дуга все все все все все все Если не оговорено особо, М и N обозначают связанную пару базисных нумераций схемы. Рис. 10.5. Глубинное остовное дерево Д. Пусть Р = (р\, ...р.,)— простой пусть по G и M(pi) = min : j e [1 : .s’]}. Тогда любая вершина пути Р является М-достижимой в G из вершины pt. Е. Л'(рс)= Л/(р0) = 1 и любая вершина р схемы как М-достижима, так и N-дости- жима из вершины ро. Ж. Для любой вершины р&Х и любой вершины q е N(p) следующие свойства эквива- лентны: q— начальная вершина N{p)-, q— входная вершина N(p)', в q заходит N-прямая дуга из вершины, N-номер которой меньше N(p). 3. Для любого i е [1 : и] подграф N(i) является сильно связным.
Глава 10. Потоковый анализ программ 747 И. Для любой вершины р е X М(р) = пйп{Л/(<7) . q е N{p}} и любая вершина q е N{p) является М-достижимой из р. К. Для любых двух различных вершин р и q N-области N(p) и N(q) либо не пересека- ются, либо одна из них является собственным подграфом другой. Нумерация F схемы G называется разумной, если выполняются следующие утвер- ждения: для любых двух вершин р и q, таких что р обязательно предшествует q, F(p) < F(q)-, если G — аранжируемая схема, то F является ее аранжировкой. JI. Нумерация Nявляется разумной нумерацией схемы. М. Если G — сводимая схема, то ее дуга является N-обратной тогда и только то- гда, когда она является дугой назад. В общем случае М не является разумной нумерацией, что демонстрирует пример схемы, изображенной на рис. 10.6. Тем не менее, для любых вершинpwq выполняет- ся М(р) < М(д), если р обязательно предшествует вершине q. Рис. 10.6. Прямая нумерация схемы Н. В сводимом графе G вершина q обязательно предшествует вершине р тогда и только тогда, когда q принадлежит каждому N-nymu от начальной вершины р^ графа G до р. 10.2. Гамачное представление уграфов Задачи анализа гамаков в программах возникают во многих системах автоматизации программирования, например в оптимизирующих трансляторах. Любая программа представима в виде иерархии альтов, являющихся простыми и составными гамаками. Помимо универсальной применимости, такое гамачное представление программы обладает следующими важными чертами: оно однозначно, не требует изменения ал- горитма обработки программ при его факторизации, а также выделяет фрагменты, способные к перемещению в программе. 10.2.1. Иерархия вложенных альтов Пусть А — некоторое множество альтов уграфа G, содержащее альты Н} и Н2. Альт Д непосредственно вложен в Н2 относительно А, если Н} с Н2 и в А не существует альта Н3 такого, что Ht cl^c/Г Альт Н, называется внутренним альтом относи- тельно А, если в А не существует альтов, непосредственно вложенных в //,, и внеш- ним альтом относительно А, если в А не существует альта, в который Н\ непосредст- венно вложен.
748 Часть II. Применение графов и граф-моделей Множество нетривиальных альтов А называется иерархией вложенных альтов уграфа G, если G е А и для любых двух альтов из А либо их пересечение пусто, либо один из них целиком содержится в другом. Последовательность уграфов Go, Gj, Gr называется представлением уграфа G в виде иерархии вложенных альтов А (A-представлением уграфа С), если Go = G, Gr— тривиальный уграф и для любого i е [1 : г] выполняется G, = Z>,(G), где В,— множество всех внешних альтов относительно и{А2: j е [1 : i]};A,— множество всех внутренних альтов относительно А - (<j{A7: j е [1:/)}). Пусть G обозначает уграф, представленный на рис. 10.7, и пусть А = {[1:4], {2,4}, [5:12], [13:15], [7:9], {6,12}, {10}, {11]}, [1:16], [7:11]}. Тогда Я, = {{2,4}, {6,12}, [7:9], [13:15], {10}, {11}}, А2 = {[1:4], [7:11]},Л3 = {[5:12]}, А4 = {[1:16]}, S, = А„ В2 = = А2и {{6,12}, [13:15]}, В3 = А3 {[1:4], [13:15]}, В4 = А4. Множество всех гамаков уграфа может содержать пересекающиеся гамаки, каждый из которых не является подграфом другого (например, во всех линейных уграфах с числом вершин больше двух). Гамак уграфа называется разложимым, если его мож- но представить как объединение двух непересекаюшихся гамаков, и неразложимым (или простым) в противном случае. Максимальный разложимый гамак называется составным. Например, уграф G (см. рис. 10.7) содержит 11 простых гамаков: [1:4], {2,4}, {3}, [5:12], [13:15], [7:9], {6, 12}, {8}, {10}, {11}, {16} и два составных: [1:16], [7:11]. Пусть Г(-обозначает множество всех нетривиальных простых и составных гамаков. А. С&Г(; и если два гамака из Гс пересекаются, то один из них целиком содержится в другом. Б. Подграф Н2 является нетривиальной линейной компонентой составного гамака Н} тогда и только тогда, когда Н2 — гамак, непосредственно вложенный в Н} отно- сительно Гс,.
Глава 10. Потоковый анализ программ 749 В. Не существует таких двух составных гамаков, один из которых непосредственно вложен в другой относительно Г(;. Г. Подграф Н является нетривиальным гамаком уграфа G тогда и только тогда, когда либо И е Г(,, либо Н образован вершинами такой непустой последовательно- сти линейных компонент Н\, Н, некоторого составного гамака, что для любого i е (1 :г] начальная вершина Н, является конечной вершиной Н,\. Гамачным представлением уграфа G называется его Ц,-представление. На рис. 10.8 приведены уграфы Gb G2, G3, G4 гамачного представления уграфа G (см. рис. 10.7). Рис. 10.8. Гамачное представление управляющего графа Пусть А — некоторая иерархия вложенных альтов уграфа G. Специальная реализация ^-представления уграфа G в виде одного графа GA = (У, Z), называемого А-графом, кодирует всю последовательность Go, Gb ..., G,.. Множество вершин У—объединение множеств вершин А'(), .., Хг всех уграфов Go, Gh ..., Gr, а множество дуг Z распада- ется на подмножества Z\ Z"m Z'" внутренних, внешних и фиктивных дуг соответст- венно и строится по следующим трем правилам: □ (q, р) е Z' если для некоторого i е (0:г) дуга (q, р) принадлежит альту уграфа G,_(, стягиваемому в вершину при переходе к у графу G,; □ (q,p) е Z", если для некоторого / е (0:г] в графе G,_| имеется дуга, соединяющая вершину q с начальной вершиной альта, который при переходе от С,А к G, стяги- вается в вершину р\ П (срр) е Z'", если для некоторого i е (0:г] альт с начальной вершиной р уграфа G#I стягивается в вершину q уграфа G,. Гамачное представление уграфа G (см. рис. 10.7 и 10.8) будет реализовывать Л-граф, представленный на рис. 10.9. Здесь фиктивные дуги графа изображены штриховыми
750 Часть II. Применение графов и граф-моделей линиями и используются следующие обозначения вершин: 1—16— вершины уграфа G; 17, 18, 20—22 и 24— вершины уграфа Gb соответствующие альтам {2, 4}, {6, 12}, [7:9], {10}, {11} и [13:15]; 25 и 19— вершины уграфа G2, соответствующие альтам [1:4] и [7:10]; 23 — вершина уграфа G3, соответствующая альту [5:12], а 26 — вершина уграфа G4, соответствующая альту [1:16]. Рис. 10.9. Д-граф 10.2.2. Нумерации К и L Нумерация К уграфа G, в котором п = |А], определяется как последний член К„ после- довательности нумераций К\, К2,..., К„, в которой А?| — обратная нумерация уграфа G и для любых /е[1 :п) и р, q е Xсправедливы следующие два свойства: если реК,{1: i - 1], то Ki+i(p) = если р, q е К,[1:п], то К,+](р) < KM(q) тогда и только тогда, когда либо р е К,(0 и q g либо К,{р) < K{q) и {/?, q} c K,(i) или {p,q} гт K/z) = 0. Рассмотрим уграф G, представленный на рис. 10.10, а, именами вершин которого являются их Л/-номера, а нумерация К задается расположением вершин. Нумерация К для G показана на рис. 10.10, б. Здесь К\ = К2 = N, К3 = К4 = К5 = К6 = К2 = К. Пусть F— некоторая нумерация уграфа G и i, j е [1:«]. F-линией в [z:j] называется множество всех тех вершин подграфа F[z:j], из которых в нем F-достижимы выход-
Глава 10. Потоковый анализ программ 751 ные вершины. F-ранг вершины q в [z:j] равен max(z, {F(p): р е А}), где А — множест- во всех тех вершин F-линий в [/:/], из которых F-достижима вершина q. Рис. 10.10. Нумерации уграфа. а — /V-нумерация б—К-нумерация, е — /.-нумерация Для уграфа G (см. рис. 10.10, б) F-линией в [2:6] является множество вершин {2, 4, 5}, F-ранг вершин 2—6 в [2:6] равен 2, 2, 4, 5, 5 соответственно. Нумерация L уграфа G определяется как последний член £0 последовательности £„, L„ h ..., Lo, в которой L„ = К и для любых z е [1:«] и р, q е X справедливы следующие два свойства: если p^L,[i:i + |£,(z)| — 1], то L,-](p') = L,(p)-, если q, р е L\i:i + |£,(z)| - 1], то Lj-Sp) < Д-|(?) тогда и только тогда, когда либо р и q имеют один и тот же £,-ранг в [z:z + |£,(z)| - 1] и L,(p) < Lt(q), либо 6,-ранг вершины q превышает Д-ранг вершины р b[z:z + |£,(z)|-l]. Для уграфа G и его некоторой нумерации К (см. рис. 10.10,6) 6-нумерация пред- ставлена на рис. 10.10, в. Здесь £7 = L6 - L5 = L4 = L3 = L2 = К, £, = Lo~ L, причем £2[2:2 + |£2(2>| - 1] = [2:6] 10.2.3. Алгоритм К-нумерации -------------------------Задача-------- Дано. Уграф G = (X, U,p0, qo), состоящий из п вершин и m дуг. Требуется. Построить нумерацию К.
752 Часть II. Применение графов и граф-моделей --------Решение------------ Метод. проц ПЕРЕНУМЕРАЦИЯ-1 (/: цел; F, Н: нумерация) = 1. А := ОБЛАСТЬ^, F1(/)); k:=i;l:=i + |А|; 2. для г от / до п цикл 3. q := F'Xry. 4. если q е А то к) := (к, к +1) 5. иначе (/7(g), /):=(/,/+ 1) все все; 6. (F, Н):=(Н, F) все; функ К-НУМЕРАЦИЯ (G: уграф) = 1. F, Н. нумерация; 2. Вычислить в F обратную нумерацию уграфа G, выполняя алгоритм 2.2.16; 3. для / от 1 до л цикл ПЕРЕНУМЕРАЦИЯ-1 (/', F, Н) все; 4. возврат F все А. Временная сложность алгоритма составляет О(пт) времени. 10.2.4. Алгоритм /.-нумерации --------3 адач а----------- Дано. Уграф G = (X, U, р0, q0), состоящий из п вершин и т дуг. Требуется. Построить нумерацию L. --------Решение------------ Метод. функ РАНГ(/,р цел; F: нумерация) = 1 ЛИНИЯ = {р е х : р — выход F[/g]}; 2. R разметка = {(р, /): p<F[i.j]}^{(p, О.) : р £ F[/g]}; 3. для г от; до / через -1 цикл 4 p:=F\r), 5. если реЛИНИЯ то 6. для всех q из ПРЕД(р) цикл 7 если F(q) е [>:г] то ЛИНИЯ <- q все все все все 8. ДЛЯ Г ОТ I до j цикл 9 р:=Л1(г);
Глава 10. Потоковый анализ программ 753 10. если р е ЛИНИЯ то R(p) := F(p) все; 11. для всех q из ПРЕЕМ(р) цикл 12. если F(q) е [г: j] то R(q) := max(R(q), R(p)) все все все; 13. возврат R все; проц ПЕРЕНУМЕРАЦИЯ-2 (/: цел; F, Н: нумерация) = 1. j := i + | ОБЛАСТЬ^, Г1(0) I - 1; 2. R = РАНГ(/, J, F); ЧИСЛО = {(А,0): k g [i:j + 1]}; 3. для всех peF[i:j\ цикл ЧИСЛО(/?(р)+1) := ЧИСЛО(Н(р)+1)+1 все; 4. для гот i до j цикл ЧИСЛО(г+1) := ЧИСЛО(г+1)+ЧИСЛО(г) все; 5. для г от 1 до п цикл 6. р := F\гу. 7. если гсру] то 8. (Н(р), ЧИСЛО(Я(р))) := (/ + ЧИСЛО(Я(р)), ЧИСЛО(Я(р)) + 1) 9. иначе Н(р) = F(p) все все; 10. (F, Н) := (Н, F) все; функ L-НУМЕРАЦИЯ (G: уграф) = 1. F. Н: нумерация; 2. F := К-НУМЕРАЦИЯ(С); 3. для тот п до 1 через -1 цикл ПЕРЕНУМЕРАЦИЯ-2(г, F, Н) все; 4. возврат F все Построение нумерации L осуществляется в соответствии с ее определением (см. разд. 10.2.2). Функция РАНГ вычисляет F-ранг вершин в [z:j], используя пере- менную ЛИНИЯ для хранения Е-линии в [ку]. Процедура ПЕРЕНУМЕРАЦИЯ-2 пе- ревычисляет нумерацию F, осуществляя переход от L, к L,_}. В ней переменная ЧИСЛО имеет следующий смысл: для любого t е [/:у] значением ЧИСЛО(г) в момент перехода от оператора 9 к оператору 10 является количество тех вершин р e F[i:j\, у которых либо R(p) < t, либо R(p) = t и F(p) < t. А. Временная сложность алгоритма L-нумерации составляет О(пт). 10.2.5. Свойства нумераций К и L Пусть М и N— пара связанных базисных нумераций уграфа G, на основе которых построены нумерации К2,..., К„ = К = Ln, Ln-\,..., Lo = L. К. Для любого i е [1 :п] и любой вершины р <еХ справедливо Ki(p) = N{p).
754 Часть II. Применение графов и граф-моделей Б. Для любой дуги (р, q) уграфа G эквивалентны следующие свойства: N(p) < N(q)', К,(р) < K,(q) для любого i е [1 :п]; L,(p) < £,(</) для любого i е [0:л]. В. Для любых i е [ 1 :и] uj е [0 :л] нумерации KuL являются разумными. Пусть для любого фрагмента 5 и любой вершины р уграфа G определены: МНОЖ1 (.S', р) = {v е ПРЕЕМ(м-) : w е S и М(у) < М(р)}, МНОЖ2(5, р)= {v е ПРЕД(и): w е S, w * р и Цу) < Цр)}, МНОЖЗ (S, р) = {v е ПРЕЕМ(и’) : w е .S, М(у) > М(р) и £(v) < Цр) }, МАКС1 (.S, р) = max(£(p), {£(v) : v е ПРЕЕМ(к), w е S и Л7(г) > Л/(р)}), MAKC2(.S, р) = тах(£(р), {£(v) :v е ПРЕД(и), w е £ и w * р }). Г. Подграф Н уграфа G является гамаком с начальной вершиной р и конечной q тогда и только тогда, когда выполняются следующие условия: Н = ЦЦр) : Цр) + + Н- 1]; /И(р) < М(у) для всех v <= Н; МНОЖ2(Н, р) = МНОЖЗ(Н, р) = 0; р ё ПРЕЕМ(^); МAKC2(tf, р) < |Н\ + Цр); либо МНОЖ 1 (И, р) = 0 и МАКС 1 (Н, р) = Цр) + \Н] = L(q), либо МНОЖ1(//,р) = {q} и МЛКС1(/£ р) < Цр) + |//|. Д. Пусть для подграфа S = ЦЦр) : Цр) + /], где t > 0, справедливо хотя бы одно из следующих условий МНОЖ2(5, р) * 0, МНОЖЗ(5, р) * 0, M(q) < М(р) для конечной вершины q гамака S, S имеет несколько конечных вершин, причем М-номер одной из та — меньше М(р). Тогда для любого г такого, что r> t, не существует гамака ЦЦр): Цр) + г]. 10.2.6. Алгоритм выделения гамаков ---------Задача---------- Дано. Уграф G = (X, U, р0, q0). Требуется. Выделить все гамаки уграфа G. ---------Решен ие-------- Метод. проц ГАМАКИ(С: уграф) = 1. Построить нумерации М и L уграфа G, выполняя алгоритм, рассмотренный в разд. 10.2 4; 2. для всех р из X цикл 3. (МАКС1, МАКС2, МНОЖ1) := (Цр), L(q), истина); 4. Пометить каждую вершину из ПРЕД(р); 5. ВЫДЕЛЕНИЕ: для к от Цр) рр п цикл 6. w := L '(k); 7. для всех v из nPEEM(w) цикл 8. если M(v) < М(р) то 9. если -1 МНОЖ1 то 10. завершить ВЫДЕЛЕНИЕ при q * v 11. иначе (q, МНОЖ1) := (v, ложь) все
Глава 10. Потоковый анализ программ 755 12. иначе завершить ВЫДЕЛЕНИЕ при ЦУ) < Цр); 13. МАКС1 := max(MAKC1, L(v)) все все; 14. еслии/^рто 15. для всех v из ПРЕД(м) цикл 16. завершить ВЫДЕЛЕНИЕ при Цу) < Цр)~ 17. МАКС2 := max(MAKC2, L(v)) все все; 18. если МН0Ж1 то 19. если (МАКС1 < k) л (МАКС2 < к) л (q не помечена) то 20. ЦЦр):к] — гамак; завершить ВЫДЕЛЕНИЕ все 21. иначе если к = л то ЦЦр): л] — гамак 22. иначе если (МАКС1 = k+1) л (МАКС2 < к) л (вершина L“1(k + 1) не помечена). 23. то ЦЦр): к] — гамак все все все все; 23. Убрать пометки с вершин из ПРЕД(р) все все Основывается на свойствах 10.2.5. Г, Д нумераций М и L уграфа G. Гамак L[L(p) : А], выделяемый оператором 21, имеет конечную вершину q, гамак ЦЦр): А], выделяе- мый оператором 27, имеет конечную вершину L~\k + 1), а гамак ЦЦр) : и], выделяе- мый оператором 21, не имеет конечных вершин. А. Алгоритм затрачивает О(тп) времени на выделение всех гамаков уграфа G, где пит — количества вершин и дуг уграфа G. 10.3. Отношения обязательного предшествования и обязательной преемственности Отношения обязательного предшествования и обязательной преемственности играют важную роль в различных алгоритмах семантической обработки программ. Они до- вольно просты для обнаружения и кодируют достоверные отношения частоты выпол- нения групп операторов и переходов, принадлежащих одним и тем же зонам.
756 Часть II. Применение графов и граф-моделей 10.3.1. Отношение доминирования и их свойства Напомним, что вершина р обязательно предшествует вершине (или доминирует над вершиной) q в уграфе G = (К, Е, р0, <у0), если р принадлежит каждому пути по G отри до <7о- Она обязательно следует за вершиной (или постдоминирует) q, если р при- надлежит каждому пути по G от q до q0. Непосредственно из определения отношения доминируемости (обязательного пред- шествования) получаем следующий алгоритм нахождения доминаторов (обязатель- ных предшественников) в уграфе G. Для каждой вершины v р0 необходимо выполнить следующие действия. Основной шаг. Определить посредством поиска от р0 множество всех вершин S, дос- тижимых из р0 на путях, не содержащих вершину v. Множество H{v}\S состоит в точности из тех вершин уграфа, которые доминируются вершиной v. Теперь, зная множество вершин, доминируемых каждой вершиной, очевидным обра- зом строим доминаторное дерево. Каждое выполнение основного шага занимает О(т') времени, и алгоритм осуществля- ет п — 1 выполнений основного шага. Таким образом рассмотренный алгоритм имеет временную сложность О(пт). Для вычисления всех доминаторов для каждой вершины графа можно воспользовать- ся также следующим алгоритмом. Алгоритм 10.2 Дано. Управляющий граф G = (V, Е, р0). Требуется. Найти для каждой вершины ре V множество ее доминаторов D(p). Метод. функ ДОМИНАТОРЫ = 1- D = {(ро, ро)} и {(р, V): р г ро}; 2. пока D уменьшается цикл 3. для всех pe(V- {ро}) цикл D(p) := {р} и (n {D(q) q е ПРЕД(р)}) все все; 4 возврат D все Заметим, что данный алгоритм является вариантом итеративного алгоритма нахож- дения стационарной разметки (см. разд. 10.5.4)-, его сложность О(п2) расширенных операций. Заметим также, что отношение обязательной преемственности в уграфе G совпадает с отношением обязательного предшествования в графе, который получается из G заме- ной ориентации дуг на противоположную и изменением ролей у вершин р0 и qt> : ро становится конечной вершиной, a q0 — начальной. Что позволяет использовать алго- ритм выявления обязательного предшествования для построения дерева обязательной
Глава 10. Потоковый анализ программ 757 преемственности. Поэтому в дальнейшем мы ограничимся рассмотрением задачи нахождения обязательных преемников вершин в уграфе. 10.3.2. Семидоминаторы Известные быстрые алгоритмы построения дерева доминаторов используют схему вычисления, состоящую из следующих трех этапов. Первый этап осуществляет поиск в глубину на исходном уграфе G = (У, Е,р0), начи- ная с вершины ро- На этом этапе приписываются Л7-номера вершинам уграфа G и строится дерево поиска Т с корнем р0. Рис. 10.13 содержит пример дерева поиска для уграфа рис. 10.11, доминаторное дерево которого приведено на рис. 10.12. Справедливо следующее свойство путей. А. Если v и w — такие две вершины, что М(у) < M(w), то любой путь от v до w дол- жен проходить через одного из общих предшественников вершин v ttw в Т На втором этапе для каждой вершины w ф р0 вычисляется ее так называемый семидо- минатор sdom(w), определяемый следующим образом в терминах семидоминаторных путей. Некоторый P=(y0=r, V|, v2,..., vv) называется семидоминаторным (или Sdom пу- тем), если Л/(г,) > M(w) для всех i, 1 < i<k. Пусть множества SD(v) обозначает множество всех вершин, из которых существует семидоминаторный путь в w. Тогда sdom(w) — эта та вершина из SD(y), которая име- ет наименьший /и-номер, т. е. М(у) = min{A/(r) : г е SD(v)}.
758 Часть II. Применение графов и граф-моделей Рис. 10.13. Поиск в глубину для уграфа, начиная из вершины R (сплошные стрелки — дуги дерева поиска, штриховые стрелки — дуги, не принадлежащие дереву, а в скобках указаны /W-номера вершин и семидоминаторы вершин) Третий этап алгоритма осуществляет собственно вычисление непосредственных до- минаторов idom(x) всех вершин х уграфа G и строит доминаторное дерево. При формулировании свойств семидоминаторов и описании алгоритмов выявления доминаторов будем отождествлять имена вершин уграфа с их Л/-номерами (напри- мер, писать p<q, если М(р) < а также использовать обозначения х—> у их —>+у, где х ->*у, если х является предшественником вершины у в дереве Т, и х -> у. если х —>* у и х у.
Глава 10. Потоковый анализ программ 759 Справедливы следующие свойства семидоминаторов. Б. Для любой вершины w, отличной от р0, имеем idom(w) —>+ w, sdom(w) —>+ w, idom(w) —»* sdom(w). В. Пусть v, w — такие две вершины, что v —>* w. Тогда Г —>* idomfw) или idom(w) —idom(y). Г. Пусть w р0 и каждая вершина v, для которой sdom(w) —>+ v ->* w, удовлетворя- ет условию sdomly) > sdom(yv). Тогда idom(w) = sdom(w). Д. Пусть w ро и v — вершина, которая среди таких вершин v, что sdom(w) —» v ->* w, имеет минимального семидоминатора sdomfy). Тогда sdom(v) < < sdomlyv) и idomfy) = idom(w). Е. Пусть w*p0 и v — вершина, которая среди таких вершин v, что sdom(w) —>+ v —>* w, имеет минимального семидоминатора sdom(y). Тогда idom(w)—\.S^°m^W^’ eCJlU sd°m(w)—sd°m(y) \idom(y), иначе. Ж. Для любой вершины w * р0 sdom(w) = minify: (у, w) €= Е, v < w} U {sdom(f) : r > w, существует (v, w) e E такая, что r —>*v }). 10.3.3. Алгоритм Ленгауэра — Тарьяна Рассмотренные свойства семидоминаторов позволяют уточнить схему нахождения обязательных предшественников (доминаторов), рассмотренную в разд. 10.3.2, в виде алгоритма, последовательно исполняющего следующие шаги. Шаг 1. Выполняется поиск в глубину. Вершинам приписываются их ЛУ-номера от 1 до я в порядке обхода уграфа, начиная с вершины р0. Инициализируются перемен- ные, используемые на последующих шагах. Шаг 2. С использованием свойства 10.3.2, Ж вычисляются семидоминаторы всех вершин уграфа. Вершины обрабатываются в порядке убывания их ЛУ-номеров. Шаг 3. С использованием свойства 10.3.2, Е неявно определяются непосредственные доминаторы вершин. Шаг 4. В процессе обработки вершин уграфа по убыванию их ЛУ-номеров произво- дится явное построение непосредственных доминаторов вершин. В процессе работы алгоритма вычисляются следующие атрибуты вершин: □ parendw) — вершина, являющаяся отцом вершины w в дереве поиска в глубину Т; □ semilyv) — число, удовлетворяющее следующим свойствам: • semi(yv) = 0 до тех пор, пока w не получает своего ЛУ-номера; • semi(w) = M(w) после получения вершиной w ее ЛУ-номера, но до вычисления ее непосредственного доминатора:
760 Часть II. Применение графов и граф-моделей • semi(w) = A/(zc/ozzz(vv)) после вычисления непосредственного доминатора вер- шины vv; П bucket(yv) — множество вершин, для которых w — доминатор; П ctozn(vv) — вершина, определяемая по следующим правилам: • после выполнения шага 3, если семидоминатор вершины w является ее непо- средственным доминатором, то c/cwz(vv) — это непосредственный доминатор vv; иначе dom(yv) — это такая вершина v, что М(у) < A7(w) и непосредственный до- минатор вершины v является непосредственным доминатором вершины w; • после шага 4 zn(vv) — это непосредственный доминатор вершины w. Шаг 1 может быть уточнен следующим образом: начало 1. /И-номер = 0; 2. для всех v е I/ цикл ПРЕД(|/) := Й; semi(v) := 0 все; 3. DFS(p0) конец. DFS — это рекурсивная процедура поиска в глубину, имеющая следующее описание: проц DFS(iz: вершина) = 1. semi(v) := /И-номер := /И-номер + 1; ЛГ1(/И-номер) := v; 2. % Инициализация переменных для шагов 2, 3 и 4 % 3. для всех w е ПРЕЕМ(!/) цикл 4. если sem/(w)=0 то parent{w) := v; DFS(w) все; 5. v => nPEfl(w) все все После шага 1 происходит совместное выполнение шагов 2 и 3 алгоритма в процессе обработки вершин vv?tp0 в порядке убывания их ЛЛномеров. Во время этой обработ- ки поддерживается временная структура данных, которая представляет лес, содержа- щийся в дереве поиска в глубину. Более точно, этот лес образован множеством вер- шин Vи множеством дуг {(parent(w), w): vv — уже обработана}. Алгоритм использует следующие процедуры для работы с этой структурой: П LlNK(v, w) — добавляет в лес дугу (v,vv); □ EVAL(v) — вычисляет v, если v— корень в лесу, либо любую вершину и * р0 с минимумом seznz(zz) на пути г ->* v, где г— корень того дерева из леса, которое содержит г. При обработке вершины w алгоритм вычисляет семидоминатор вершины w с ис- пользованием свойства 10.3.2, Ж. Он присваивает semi{w) = mm{semi{EVAL(y))'. (v, w)^E}. После этого присваивания semi(w) получает ЛЛномер семидоминатора вершины w. Чтобы проверить это утверждение, рассмотрим любую дугу (v, w) е Е. Если М(у) < M(w), то v еще не обработана, и это значит, что v является корнем дерева
Глава 10. Потоковый анализ программ 761 в лесу и semify)— это ЛАномер вершины v. Таким образом, sew/(EVAL(v)) является ЛАномером вершины v. Если же A/(v) > A7(iv), то v уже обработана и не является кор- нем. Таким образом, EVAL(v) возвращает некоторую вершину w, которая среди вер- шин, удовлетворяющих условию и —и' и М(и) > имеет наименьший номер, и sew/(EVAL(v)) является ЛАномером семидоминатора вершины и. Это означает, что алгоритм корректно осуществляет минимизацию, содержащуюся в свойстве 10.3.2, Ж. После вычисления semi(w) алгоритм добавляет вершину w к множеству bucketin'и добавляет новую дугу в лес с использованием вызова процеду- ры LINK.(poren/(w), и')- Эти действия завершают выполнение шага 2 для w. Затем ал- горитм опустошает множество bucket(parenl(w)), выполняя шаг 3 для каждой верши- ны v из этого множества. Он неявно вычисляет непосредственного доминатора v по свойству 10.3.2, Е. Пусть и = EVAL(v). Тогда и является той из вершин, удовлетво- ряющих parent(w) ->+w->*v, чей семидомина гор имеет наименьший ЛАномер. Если serni(u) = semi(v), то parenl(w) является непосредственным доминатором v, и алгоритм присваивает doni(y) := parent(yv). Иначе у вершин и и v есть общий доминатор, и алго- ритм присваивает dom(y) := w. Этим завершается выполнение шага 3 для v. Шаги 2 и 3 алгоритма уточняются следующим образом: % инициализация переменных % для /’ от л до 2 через -1 цикл 1. w=M'(i) 2. Шаг 2 : для всех ve FlPEfl(w) цикл 3. и := EVAL(iz); 4. если semi(v)<semi(w) то semi(w) := semi(u) все все; 5. w => bucket(M '(semi(w)))\ LINK(parenf(w), w); 6. Шаг 3: для всех ve bucket(parent(w)) цикл 7. удалить v из bucket(parent(w)); 8. и := EVAL(iz); 9. dom(v) := если semi(u)<semi(y) то и иначе parent(w) все все все Шаг 4 просматривает вершины в порядке возрастания их ЛАномеров и заполняет ин- формацию о непосредственных доминаторах вершин, неявно найденную на шаге 3. Он имеет следующий вид. Шаг 4: начало 1. для/ от 2 до л цикл 2. w := ЛА1(/); 3. если dom(w) * М'(semi(w)) то dom(w) := dom(dom(w)) все все; 4. dom(p0) := 0 конец
762 Часть II. Применение графов и граф-моделей Прежде чем перейти к реализации процедур LINK и EVAL, рассмотрим работу алго- ритма на примере (см. рис. 10.14 и 10.15). Рис. 10.14. Состояние уграфа непосредственно перед обработкой вершины А (жирные стрелки — дуги леса, числа в скобках — semi, буквы в скобках — dom) Рис. 10.14 демонстрирует состояние графа непосредственно перед обработкой вер- шины А. Две дуги (В, А) и (R, А) заходят в А, давая 8 (ЛАномер В) и 1 (ЛАномер R) в качестве кандидатов для semi (А). Алгоритм присваивает semi(A) := 1, помещает А в bucket(R) и добавляет дугу (В, А) в лес. Затем алгоритм очищает bucket(A)={jD}. EVAL(jD) дает А в качестве вершины на пути В -*+А D с минимальным semi. По- скольку semi(A) = 1 < 8 = semi(D), idom(A) = idom(D) и алгоритм присваивает dom(D) = А. Рис. 10.15 — это состояние графа непосредственно перед обработкой вершины I. Че- тыре дуги (F, Г), (G, Г), (J, Г) и {К, I) заходят в I, определяя 3 = M(F), 2 = semi(G), 6 = senu(J) и 1 = semi(K) соответственно в качестве кандидатов для semi(T). Алгоритм присваивает semifT) := 1, помещает 1 в bucket(R) и добавляет в лес дугу (F, Г). Затем алгоритм очищает множество bucket(F), которое к тому моменту уже пусто. В разд. 10.3.5 приводится полное описание алгоритма, включающее описание пере- менных и их инициализацию. Используя свойства 10.3.2, Е и 10.3.2, Ж, нетрудно проверить, что после выполнения алгоритма cfow(v) = idom(y) для всех v -А р0, если операции LINK и EVAL корректно выполняют необходимые действия. Его временная сложность составляет О(т + и) плюс время, необходимое для выполнения п - 1 опе- рации LINK и т + п - 1 операции EVAL.
Глава 10. Потоковый анализ программ 763 Рис. 10.15. Состояние уграфа непосредственно перед обработкой вершины I (жирные стрелки — дуги леса, числа в скобках — semi, буквы в скобках — dom) 10.3.4. Реализация операций LINK и EVAL Рассмотрим два способа реализации операций LINK и EVAL: простой и усложненной. Простой способ использует сжатие пути при выполнении операции EVAL. Для пред- ставления леса, построенного с помощью операций LINK, используются два атрибута вершин графа: ancestor и label. Вначале ancestorly) = 0 и label(y) — v для любой вершины v. В общем случае справед- ливо следующее свойство: ancestorly) содержит либо нуль, если v является корнем дерева в лесу, либо отца вершины v в лесу, если г не корень дерева. Значения атрибута label у вершин вычисляются таким образом, чтобы они удовлетво- ряли следующему свойству. Пусть v — некоторая вершина, г — корень дерева (в ле- су), содержащего v, и v*, v*_|, ...,v0— такая последовательность вершин, что v*= v, v0 = г и ancestorly^) = v,_| для всех z. Пусть х является такой вершиной, что semilx) принимает минимальное значение среди вершин xe{/a6e/(v,): 1 < z < к}. Тогдах явля- ется такой вершиной, что semilx) принимает минимальное значение среди вершин х, удовлетворяющих условию г ->+ х ->* v. Чтобы выполнить операцию LINK(v,w), алгоритм присваивает ancestor{w) := v. Чтобы выполнить операцию EVAL(v), алгоритм следует по ссылкам на отцов вершин для определения последовательности v*, v*_,,..., v0, в которой vtl=v, v0 = r и ancestorly^ = v,_, для всех z, 1 < z < к. Если v = г, результатом является v. Иначе алго-
764 Часть II. Применение графов и граф-моделей ритм осуществляет сжатие пути, присваивая ancesior(yt) = г для всех z от 2 до к, одно- временно изменяя атрибуты label по правилу: если semi(label(y,_ |)) < semi(label(yi)), то labellyi) := labelly^). Затем в качестве результата выдается label(v). Указанные действия реализует следующее уточнение процедуры EVAL. функ EVAL(iz: вершина) = если ancestori/)=0 то возврат v иначе COMPRESS(v); возврат /абе/(и)все все; Здесь рекурсивная процедура COMPRESS осуществляет сжатие пути и имеет сле- дующий вид. проц COMPRESS(iz: вершина) = 1. % процедура предполагает, что ancestody) $ 0 % 2. если ancestor^)) Ф 0 то COMPRESS(ancestoz^v)); 3. если semiljabe/(ancestor^i/))) < semi(label(v)) то 4. label(v) := label(ancestor(v)) все; 5. ancestor[v) := ancestor(ancestor(y)) все все Время, необходимое для и - I операций LINK и m + и — 1 операций EVAL при рас- смотренной реализации, составляет O(wlog ri). Таким образом, простая версия алго- ритма требует O(zzrlog ri) времени. Сложный метод реализации использует сжатие пути при выполнении EVAL, но реа- лизует операцию LINK таким образом, чтобы сжатие путей выполнялось только на сбалансированных деревьях. Сложный метод использует два дополнительных атри- бута у вершин: size и child. В начале sizely) - 1 и childly) = 0 для всех вершин V. При- ведем уточненную реализацию сложного метода. функ EVAL(iz: вершина) = 1. если ancestor^v)=0 то возврат label(v) 2. иначе COMPRESS(iz); 3. возврат если semi(label(ancestor(v))) a semi(label(v)) то labelfy) иначе label(ancestoriy)) все все все; проц LJNK(iz, w: вершина) = 1. % процедура предполагает, что sizeifi) = label(O) = semi(0) = 0 % 2. s := w; 3. пока semi(label(w)) < semi(label(child(s))) цикл 4. если s/ze(s) + size(child(s))) 5 2-size(child(s)) to 5. parent(child(s)) := s; child(s) := child(child(s)) 6. иначе size(child(s)) := size(s); s := parents) := child(s) все все;
Гпава 10. Потоковый анализ программ 765 7. Iabel(s) := label(w)\ size(v) ;= size(v) + size(w); 8. если size(v) < 2size(w) to (s, childly)) := (childly), s) все; 9. пока s 0 цикл parent(s) := v; s := child(s) все все В этой реализации время, требуемое для и - 1 операции LINK и m + и - 1 операции EVAL, составляет О(т а(т, и)), где а — функция, обратная функции Аккермана. Таким образом, временная сложность алгоритма при усложненной реализации со- ставляет О(т а(т, и)). При этом если т почти линейно зависит от и, т. е. m/n = Q(log<O(IMn), то а(т, л) становится константой. 10.3.5. Общий вид алгоритма Ленгауэра — Тарьяна ---------- Задача--------------- Дано. Уграф G = (К, Е,р,^, где V= [I, л] и р0= 1. Требуется. Целочисленный массив dom[\...n], в котором dom[i] =j # 0, если j — непосредственный доминатор вершины /. ----------Решение--------------- Метод. проц DFS(iz: integer) = 1. semi(v) := /W-номер ;= /W-номер + 1; 1/е/1ех(М-номер) := label(v) := v; 2. ancestorty) := {child(v)} 0; {size(v) := 1;} 3. для всех w e nPEEM(iz) цикл 4. если semi(w) = 0 то parent(w) := v; DFS(w) все; 5. v => nPEfl(w) все все; проц COMPRESS(iz: integer) = 1. если ancestor!,ancestor!,v)) 0 to COMPRESS(ancestor(i/)); 2 если semi(label(ancestorfy))) < semi(label(v)) to 3. label(v) := label(ancestor!,v)) все; 4. ancestor^ iz) := ancestor^)) все все; функ EVAL(iz: integer) = если ancestor!,i/)=0 то возврат v иначе COMPRESS(iz); возврат label(v) все все; проц LINK(iz, w; integer) = ancestor(w) ;= v все; проц DOMINATORS = 1. integer array parent, ancestor,{child} vertex [1 ...n]; 2. integer array label, semi {size} [0..n]; 3. integer set array pred, bucketfl-.n]-, integer u,v,x;
766 Часть II. Применение графов и граф-моделей 4. Шаг 1: для v от 1 до п цикл pred(v) := bucket(v) := 0; semi(v) := 0 все; 5. DFS(po)', {s/ze(O) := labeKfi) := semi(0) := 0;} 6. для / от л до 2 через -1 цикл 7. w := i/ertex(O; 8. Шаг 2: для всех v<^pred(w) цикл 9. u := EVAL(iz); 10. если semi(u) < semi(w) то semi(w) := semi(u) все все; 11. w => bucket(vertex(semi(w)))\ LINK(parenZ(w),w); 12. Шаг 3: для всех v е bucket(parent(w)) цикл 13. Удалить v из bucket(parent(w))\ u := EVAL(iz); 14. dom(v) := если semi(u) < semi(v) то u иначе parent(w) все все все; 15. Шаг 4: для /' от 2 до л цикл w := i/ertex(/); 16. если dom(w)tvertex(serni(w)) то dom(w) := dom(dom(w)) все все; 17. dom(r) := 0 все Простая версия алгоритма состоит из рассмотренной процедуры с удалением всех тех операторов, которые приведены в фигурных скобках. Усложненная версия алгоритма состоит из рассмотренной процедуры с включением операторов, приведенных в фи- гурных скобках, и заменой процедур EVAL и LINK на следующие. проц EVAL(iz; вершина) = 1. если ancestortv) = 0 то возврат label(v) 2. иначе COMPRESS(iz); 3. возврат если semi(label(ancestor[v))) > semi(label(v)) 4. то label(v) иначе label(ancestor(v)) все все все; проц LINK (у, w: вершина) = 1. s:=w; 2. пока semi(label{w)) < semi(label(child(s))) цикл 3. если s/ze(s) = size(child(child(s))) г 2- size(child(s)) то 4. ancestor[child(s))s; child(s) := child(child(s)) 5. иначе size(child(s)) := size(s); s := ancestors) := child(s) все все; 6. Iabel(s) := labellw); size(v) := size(v) + s/ze(w); 7. если size(v) < 2 size(w) to (s, child(v)) := (child(v), s) все; 8. пока s Ф 0 цикл ancestors) := v, schild(s) все все
Гпава 10. Потоковый анализ программ 767 10.3.6. Микродеревья и их использование Идея линейного алгоритма поиска доминаторов состоит в том, чтобы выделить такие альты уграфа, чтобы: □ внутри альтов отношения доминирования вычислялись за линейное время; □ после сворачивания альтов в вершины для выявления отношения между вершина- ми, принадлежащими разным альтам, можно было бы применить алгоритм Лен- гаура— Тарьяна к фактор-графу, причем соотношение числа дуг и числа вершин в фактор-уграфе было бы почти линейным. Такие альты получили название микродеревьев. Рассмотрим следующую процедуру, помечающую вершины в дереве Т. Считается, что параметр g задан, и все вершины изначально не помечены начало 1. для всех вершин хе Г в порядке убывания их /W-номеров цикл 2. S(x) := £s(y) у-сын X 3. если S(x) > д то Пометить всех сыновей х все все; 4. Пометить корень Т конец Для каждой вершины v положим бпп(у) — ближайший помеченный предшественник. Функция бпп разбивает Т на микродеревья следующим образом (рис. 10.16). Пусть v помечена; тогда D(v) = {х : бпп(у) = v} — микродерево, a root(JXy)) = у — корень микродерева D(v). Пусть micro(x) обозначает микродерево, содержащее х. Микродерево называется нетривиальным, если оно содержит хотя бы один лист де- рева Т. Все остальные микродеревья состоят ровно из одной вершины и называются тривиальными. Вершина у, составляющая тривиальное микродерево, называется специальной, если каждый потомок v— корень нетривиального микродерева; на рис. 10.16, С и Е — такие вершины. Пусть Р = {и = х0, Х|,..., Хк 1,хк= v) — путь по уграфу G. Р - внешний доминаторный путь (или XDOM-путъ), если: □ Р является Sdom путем, т. е. х, > v для всех 1 < i < к', □ Хо, ..., Хк । £ micro(y). Внешний доминатор вершины у обозначается через xcfozn(v) и определяется как min{{v} О {и : существует ЛООЛАпуть из и в у}}. Если v образует тривиальное микродерево, то xdom(v) = semi(y). Р называется продвинутым внешним доминаторным путем (или PXDOM-путем), если х, > root(micro(v)) для всех Z, 1 < z < к - 1. Продвинутый внешний доминатор вершины у обозначается через pxdomfy) и опреде- ляется как min {и : есть PXDOM-путь из и в у}.
768 Часть II. Применение графов и граф-моделей Рис. 10.16. Микродеревья и ближайшие помеченные предшественники вершин уграфа Для уграфа (см. рис. I0.16) путь P=(c,j, I) является XDOM-путем от с к I. Причем других ХЕЮМ-путей в уграфе нет. Здесь xdom(l) = 2. Путь Р = (г, b, е, g, /, л, Г) явля- ется PXDOM-путем и pxdom(l) = 1. А. Для каждой вершины, составляющей тривиальное микродерево, pxdom(y)=seini(y). Б. Если idom(y) £ microfy), то idomfy) —>* pxdom(y). С использованием микродеревьев алгоритм выявления отношения доминирования может иметь вид последовательности из следующих двух шагов: П определить для каждой вершины v, верно ли, что idomfy) е microfy), и если это так, то вычислить idom(yp, П использовать алгоритм Ленгаура—Тарьяна для вычисления доминаторов для всех таких вершин, что idomfy) g micro(y). Рассмотрим правила вычисления внутренних доминаторов. Для нетривиального мик- родерева введем понятие расширенного графа aug(T) следующим образом. Пусть G(T)— подграф уграфа G, построенный на вершинах микродерева Т. Тогда граф aug{T) — это граф G(T), к которому добавлены следующие дуги и вершины: □ вершина t, называемая корнем aug(T) и обозначаемая через root(aug(T)); □ так называемая синяя дуга (z, v) для каждой вершины v е Т такой, что есть дуга {и, v) е Е для некоторой и£Т. Для вершины х ее внутренним непосредственным предшественником (обозначение iidom(x)) называется idom(x) в графе aug(micro(x)).
Глава 10. Потоковый анализ программ 769 В. Если iidom(x) Ф root(aug(micro(x))), mo idom(x) = iidomfx). Г. Если iidomfx) — root(aug(micro(x))), mo idom(x) £ micro(x). Для вычисления pxdom используется атрибут вершины label(v) в лесу (как в алгорит- ме Ленгауэра—Тарьяна), причем labelly) = v изначально. Пусть EN(v) - {х : (х, v) е Е, х g microfy)}— множество внешних соседей вершины v. Следующий алгоритм обрабатывает вершины в порядке убывания /И-номеров. Ш а г 1. Для v е Т. □ В = {label(x): х G £Mv)}; □ С = {label{eval(jjarent(t-oot{micro{x))))) : х е EN'(v) и не верно, что х ->* v}; П labeKy) = min({v} CJ В CJ С). Ш а г 2. Пусть ve Т и У(у) — множество вершин и из Т таких, что есть путь из и в v, состоящий только из вершин G(T). Положим labeKy) = mm{label(y): у е K(v)}. Ш а г 3. Если Ттривиальное микродерево, то выполняем linkiy). Д. После выполнения шага 1 имеем label(x) = xdom(x) для всех х е Т. Е. После выполнения шага 2 имеем label(x) = pxdom(x) для всех х е Т. Для вычисления доминаторов можно воспользоваться следующими свойствами: Ж. Для любой вершины v существует такая вершина w G microfy), что w —>* v; pxdom(y) = pxdomfw); pxdontfyv) = sdomlyv)', iidom{w) = root(aug(niicro{w))). 3. Пусть v uw — вершины в микродереве T такие, что w —>* v, pxdomly) — pxdom(w), iidomfy) = iidomlyv) — root(aug(E)); тогда idom(y) = idom(w). 10.3.7. Линейный алгоритм Бухбаума — Каплана — Роджерс ---------Задача-............. Дано. Уграф G = (V, Е, root), где И= [1: п] и root = 1. Каждой вершине графа может быть сопоставлена одна из трех пометок: Plain, MTroot или TrivMTroot в зависимости оттого, является ли вершина не корнем в микродереве, корнем нетривиального мик- родерева или корнем тривиального микродерева. Требуется. Целочисленный массив idom[l,... п], сопоставляющий каждой верши- нет ее непосредственного обязательного предшественника idomfy], ---------Решение------------- Метод. проц Partition^. вершина) = 1. M(v) := /W-номер := /W-номер + 1; Пометить вершину v как посещенную 2. semidamty) := 0; bucketty) := 0; link(v) := 0; weighty) := 0; 25 Зак. 202
770 Часть II. Применение графов и граф-моделей 3. Iabel(v) := M(v); statusly) := Plain; sizely) ;= 1 4. vertices(M(v)) := v; pmtroot(v) := parentty); 5. для всех senPEEM(v) цикл 6. если s не посещалась то 7. parentfs) := v; Partition(s)', size(v) := size(y) + size(s) все; 8. v => FIPEfl(s) все; 9. если size(v) > g то 10. если все сыновья s имею/ пометку Plain то weighty) := 1 все; 11. Дать пометку MTRoot сыновьям вершины v, имеющим пометку Plain; 12. status(v) := TrivMTRoot все все; проц Computedom(root: вершина)= 1. для всех veTв порядке убывания /W-номеров цикл 2. если statusfy) = TrivMTRoot то Processl/(v) 3. иначе если v не был обработан то ProcessMT(v) все все все 4. для всех ve(T-{root}) в порядке возрастания их /W-номеров цикл 5. если samedomly) Ф null то icfom(v) := idorv{samedomly)) все все все проц ProcessV(v: вершина) = 1. Iabel(v) := M(v); 2. для р е ПРЕД(и) цикл 3. если /аЬе/(р) < labelly) то labeKy) := label(p) все 4. если М(р) > M(v) то evalnode := Eval(pmtroot(p)) 5. если label(evalnode) <label(p) то labeKy) := label(evalnode) все все все; 6. v => bucket(vertices(label(v))y,Link(parent(y)y) 7. для всех w е bucket(parent(v)) цикл 8. z := Eval(pmtroot(w)); 9. если label(z) = M(parent(v)) то idom(w) := parent(y) 10. иначе semidom(w) := z все; 11. убрать w из bucket(parent( v)) все все; проц ProcessMT(v: вершина)= 1. Найти mtroot среди вершин, начинающихся из v; 2. МТ := vertices[M(mtroot)..M(mtroor) + size(mtroor) - 1];
Глава 10. Потоковый анализ программ 771 3. Инициализация encoding; 4. isolated := true; 5. для всех v е МТ цикл 6. pmtroot(v) := parent(mtroot); labeKy) = M(v); 7. для всех р e pred(v) цикл 8. если р е МТ то включить (р, v) в encoding 9. иначе включить в encoding синюю дугу, ведущую в v; 10. если v * mtroot то isolated := false все; 11. если label(p) < label(v) то label(v) := label(p) все; 12. если М(р) > М(у) то evalnode := Eval(pmtroot(p)); 13. если label(evalnode)<label{v) то 14. Iabel(v) := label(evalnode) все все все все все; 15. iidomencoding := редуцированное encoding; 16. если iidommemo(iidomencoding) не определен то 17. iidommemo(iidomencoding) := Computeudom(encoding) все; 18. iidomsiidommemo(iidomencoding); 19. если изолированное то lsolatedPush(MT, iidoms) 20. иначе Push(MT, encoding, iidoms) все; 21. для всех и/е bucket(parent(mtroot)) цикл 22. idom(w) := parent(mtroot), Удалить w из bucket(parent(mtroot)) все все; проц lsolatedPush(MT : микродерево, idioms : массив) = 1. mtroot := МТ[0]; 2. для всех v е МТ, v * mtroot цикл 3. idm(v) := vertices(M(mtroot) + idoms(secM(v))); 4. label(v) = label(mtroot) 5. все; 6. mtroot => bucket(label(mtroot)) все проц Push(MT : микродерево, encoding вершина, idioms : массив) = 1. mtroot = MT[0]; 2. sccencoding := редуцированный ncoding; 3. если sccmemo(sccencoding) не определен то 4. sccmemo(sccencoding) := ComputeScc(mtroot, encoding) все; 5. для всех SCC e sccmemo(sccencoding) в топологическом порядке цикл 6. m := min({/a£>e/(v):v e SCC}u{label(u);(u,v) e E, и e MT, u s SCC, v e SCC});
772 Часть II. Применение графов и граф-моделей 7. для всех veSCC цикл 8. label(v) := л?; 9. если udoms[M(v) + 1]g/WTто v => bucket(label(v)) 10. иначе idomty) ;= vertices(/W(mfroot)+«doms(/W(v)+1)) все все все все; начало 1. Инициализация вычислений; Partition(root) 2. status(root) := TrivMTRoot; Computedom(root) конец 10.3.8. Инкрементальное вычисление доминаторных деревьев Задача инкрементального вычисления доминаторного дерева состоит в корректном его поддержании в ситуации, когда исходный уграф подвергается изменениям. Труд- ность задачи связана с тем, что отношение доминирования не является локальным: для двух заданных вершин р и q уграфа наличие между ними отношения доминиро- вания зависит от наличия или отсутствия путей, проходящих через вершины, неогра- ниченно удаленные как отр, так и от q. Говорят, что вершина р затронута некоторым изменением графа G, если в результа- те этого изменения изменилось отношение доминирования для р. Рассмотрим, например, уграф G и его доминаторное дерево Т, изображенные на рис. 10.17. Предположим, что изменение G состоит в добавлении дуги (2, 4). Нетруд- но увидеть, что в результате вершина 3 перестанет быть непосредственным домина- тором вершин 4, 6 и 8, т. е. все эти вершины затронуты вставкой дуги (2, 4). Заметим также, что такое добавление дуги делает граф G несводимым. Ситуация не упрощается, если изменения G состоят в удалении некоторой дуги. Здесь, как и для случая добавления дуги, затронутые им вершины (т. е. вершины, на отношения между которыми влияет это преобразование) могут находиться на произ- вольно далеком расстоянии от удаленной дуги. Для эффективного решения задачи инкрементального вычисления доминаторного дерева используются следующие конструкции. Дуга уграфа G называется J дугой, если она не соответствует дуге в доминаторном дереве, и называется D дугой, если она — дуга в доминаторном дереве. Граф, который получается из доминаторного дерева, путем добавления ./дуг исход- ного уграфа получил название DJ графа. Например, для уграфа G (см. рис. 10.17) DJ граф будет иметь вид, изображенный на рис. 10.18.
Глава 10. Потоковый анализ программ 773 Рис. 10.17. Отношение доминирования: а — уграф G, б — его доминаторное дерево Рис. 10.18. DJ граф уграфа G
774 Часть II. Применение графов и граф-моделей Доминапюрная граница DF(p) вершины р — это множество всех вершин q, таких, что р доминирует предшественника вершины <?, но не является доминатором q, отличным от q, т. е. р не является, как говорят, строгим доминатором вершины q. Понятие доминаторной границы можно обобщить на множества вершин 5, полагая по определению, что DF(5)=|^JdF(/j). реХ Наконец, итеративная доминапюрная граница IDF(S) множества 5— предел после- довательности IDFi(S), IDF2(S),IDF,(S),..., элементы которой определяются по правилам: IDF^S) = DF(S) и IDF,tl(S) = DF(S u IDF,(S)) для всех z > 1. А. Пусть добавлена дуга (р, q) в уграф G. Тогда множество затронутых вставкой этой дуги дает с множеством тех вершин из lDF(q) {q}, которые лежат в доми- наторном дереве ниже вершины г, являющейся наибольшим общим предком верши- ны р и q, т. е. z = (р, q)' их новым непосредственным доминатором станет верши- на z. Данное свойство позволяет за линейное время выполнять несложные операции над DJ графом, сохраняющие его корректность по отношению к уграфу G, изменяемому в результате добавления дуги. Алгоритм 10.3. Изменение DJ графа: вставка дуги Дано. Уграф G, а также DJ граф Т и дуга (р, q) уграфа G. Требуется. Преобразовать Т в граф Т', который был бы DJ графом уграфа G’ = Gu{(p,9)). Метод. проц ИЗМЕНЕНИЕ ПРИ ВСТАВКЕ = 1. z := nca(p.Q); 2. DA := {w: w e ({q} u IDF(q)) и iv.уровень > z.уровень + 1} 3. если z * p то Добавить J дуги (p, q) все; 4. для всех w e DA цикл 5. a := idam(m); Убрать D дугу (и, и/); 6. если (u,w) дуга в G то Добавить J дугу (и,и/) все; 7. Добавить D дугу (z, и/) все; 8. для всех w е DA цикл Изменить атрибут уровень w все все Б. Временная сложность алгоритма 10.3 составляет О(к), где к— количество дуг в подграфе DJ графа, порожденным множеством вершины поддереве с корнем пса(р, q). На рис. 10.19 приведен результат работы алгоритма для графа G (см. рис. 10.17) и добавляемой дуги (2, 4).
Глава 10. Потоковый анализ программ 775 Рис. 10.19. Добавление дуги (2,4) к уграфу G: а — измененный уграф G, б — DJ граф измененного G Несколько иная ситуация возникает, когда происходит удаление некоторой дуги (р, q). Здесь уже нельзя непосредственно вычислить множество вершин, затронутых преобразованием, или их новых непосредственных доминаторов. Введем множество вершин, возможно затронутых удалением дуги (р, q), как DA(q) = {q} u {vv e IDF(q) : w.уровень = ^.уровень}. Это множество является безо- пасной аппроксимацией множества затронутых вершин. Поскольку все новые непосредственные доминаторы всех вершин, затронутых удале- нием дуги (р, q), должны быть потомками idom(q), все изменения DJ графа происхо- дят в ST(idom(q)) — его поддереве с корнем idom(q). Рассматривается разбиение вершин ST(p) на три класса: □ возможно затронутые — те вершины, которые принадлежат DA(q)', □ псевдозатронутые — такие вершины w е ST(p), что некоторый предок вершины w, отличный от w, является возможно затронутым. Непосредственный доминатор псевдозатронутой вершины не изменяется, но его доминаторное множество может измениться; □ не затронутые — все остальные. У вершин из этого класса доминаторные множе- ства не изменяются. Например, для уграфа G, изображенного на рис. Ю. 19, и удаляемой дуги (2, 4), где IDF(4) = {3,6,8}, вершины 3, 4, 6 и 8 являются возможно затронутыми, а вершины 1 и 2 являются не затронутыми.
776 Часть II. Применение графов и граф-моделей Алгоритм 10.4. Изменение DJграфа' удаление дуги Дано. Уграф G, а также DJ граф Т и дуга (р, q) уграфа G. Требуется. Преобразовать Т в граф, который был бы DJ графом уграфа G' = = G-{(p,q)}. Метод. проц ИЗМЕНЕНИЕ ПРИ УДАЛЕНИИ = 1. DA(q) = й)и{ки'е ({<?} и IDF(q)), w. уровень = q. уровень}; 2. z := idom(qy, 3. Осуществить разбиение ST(z) на множества возможно затронутых, псевдозатронутых и не затронутых вершин; 4. для всех w е ST(z) цикл 5. Инициировать D(w) и D"(w) в соответствии с классом, которому принадлежит вершина w все; 6. флаг := истина; 7. пока флаг цикл 8. флаг := ложь; 9. для всех возможно затронутых и/ цикл 10. Пусть DT — множество всех вершин в ST(z); 11. для всех v е ПРЕД(и/) цикл 12. если v псевдозатронутая то 13. D"(v) := D(u), где и — возможно затронутый доминатор вершины v все; 14. DT := DT n (D'(p) и О"(р)) все; 15. ND(w) := {и/} и DT; 16. если D(w) * ND(w) то флаг ;= истина; D(w) := ND(w) все все все; 17. Вычислить непосредственных доминаторов для всех возможно затронутых вершин; 18. Произвести соответствующие изменения DJ графа все Алгоритм 10.4 использует разбиение D(v) для каждой v е ST(z) на два множества: статическую часть— D'(v) и динамическую часть— D"(v). Вершины из статической части продолжают доминировать v после изменения G, а вершины из динамической части обычно будут изменяться в процессе применения итеративного алгоритма для перевычисления доминаторов вершин из-за изменения G. Используются следующие правила инициализации этих множеств в операторе 5: □ если v — возможно затронутая, то D'(v) = 0 и D"(v) = {и : и е ST(p)}; □ если v— псевдозатронутая, то D'(v) = 0 и D"(v) = D(w), где w единственный возможно затронутый доминатор вершины v; □ если v не затронутая, то D'(y) = D(y) и D"(y) = 0.
Глава 10. Потоковый анализ программ 777 Рассмотрим выполнение алгоритма на графе G, его DJ графе Т и дуге (2,4) (см. рис. 10.19). Здесь £>Л(4) = {4,3,6,8), {3,4,6,8} — возможно затронутые, {5,7} — псевдозатронутые, {1,2} — не затронутые, О'(3) = £>'(3) = £>'(4) = £>'(6) = £>'(8) = 0, £>"(3) = £>"(4) = /J"(6) = £)(8) = Г, £>'(5) = {5}, £>"(5) = £>(3), D'(7) = {7}, D"(7) = £>(6), D'( 1) = {1}, £>'(2) = {1.2}, £>"( 1) = D"(2) = 0. После обработки вершины 3 на первой итерации имеем, что 1 — не затронутая вер- шина и £>(1) = £>'(1) {1}, 7 — псевдозатронутая, £>(7) = £>'(7) <-> D"(7) = {7} VJ £>(6) = = [1,8] £>( 1) n 0(7) {1} и {1,3} — доминаторное множество вершины 3 на завер- шении первой итерации. В, Временная сложность алгоритма 10.4 составляет О(п2), где и— число вершин уграфа 10.3.9. Алгоритм нахождения доминаторов в сводимом уграфе ---------Задач а----------- Дано. Сводимый уграф G = (X, О, р0). Операции. Имеются логические (покомпонентные) операции над шкалами пересе- чения ® и объединения ф. Требуется. Для каждой вершины р е X вычисляется такая шкала О, q-ii компо- нент которой равен 1, если вершина q обязательно предшествует вершине р, и равен О в противном случае ---------Решение----------- Метод. Выполнение алгоритма состоит из двух последовательных этапов. Первый этап связан с установлением обратной нумерации N уграфа G, второй приведен. Ал- горитм имеет линейную сложность и использует свойство о том, что в сводимом гра- фе G вершина q обязательно предшествует вершине р тогда и только тогда, когда q принадлежит каждому Л'-пути от начальной вершины ро графа G до р (свойство 10.1.4, Н). проц ОПРЕД = 1. D разметка = {(р,(0р_0n-₽)): р е X} 2 для £ от 2 до л через 1 цикл 3. р := Л/1(к); Г:= (1Л); 4. для всех q из ПРЕД(р) цикл 5. если N(q) < N(p) то Г = Т® D(q) все все 6 D(p) := D(p) Ф Т все все
778 Часть II. Применение графов и граф-моделей 10.4. Структурная сложность программ Понятие сложности программы включает в себя много различных факторов, таких как трудность написания программы, отладки и сопровождения, понимания и т. д. Очевидно, что сложность программы зависит от человека (пишущего или читающего программу), от имеющейся документации и, конечно, от самой программы, от так называемой структурной сложности программы. 10.4.1. Понятие сложности программы Сложность самой программы зависит в свою очередь: П от размера программы; □ от ее структур данных; □ от структур управления, определяемых логикой программы; □ от правильного ее разбиения на модули; □ от внутренних связей каждого модуля; □ от межмодульных связей в программе. Отсюда вытекает, что сложность программы является, по терминологии теории изме- рений, латентной (скрытой) переменной, в отличие от переменных-индикаторов, которые поддаются непосредственному измерению. Функцию, устанавливающую значение латентной переменной того или иного свойства программы, исходя из зна- чений каких-то заранее выбранных индикаторов, называют оценочной функцией или мерой', область ее значений — оценочным множеством', совокупность индикаторов- аргументов— метрикой измерения; числовой параметр, пробегающий оценочное множество, — показателем латентной переменной измеряемого свойства. В общем случае латентная переменная связана со своими индикаторами некоторым вероятно- стным способом: каждому значению индикатора соответствует вероятностное рас- пределение возможных значений латентной переменной и наоборот. В тривиальном случае латентная переменная просто отождествляется с одним из возможных индика- торов; в общем случае операционным определением латентной переменной может служить тесно связанная группа взвешенных индикаторов. Выделять группы индика- торов можно, например, с помощью факторного анализа. При этом выбранную сис- тему индикаторов можно согласовать так, чтобы ранжирование данной группы объ- ектов обеспечивала максимальную корреляцию с ранжированием по каждому из индикаторов в среднем по всей системе индикаторных распределений при фиксиро- ванном способе определения этого среднего. Тогда в качестве операционного опре- деления данной латентной переменной будет выступать выбранная система индика- торов вместе со способом определения средней корреляции разных индикаторных расшифровок. Отсюда следует, что одной из важных проблем метрологии качества программ явля- ется проблема разработки метрик и мер, способных ранжировать программы по неко- торому критерию качества, и создание программных инструментов, обеспечивающих их вычисление.
Глава 10. Потоковый анализ программ 779 В метрической теории программ обычно выделяют семь направлений: 1. Измерения надежности программных систем, направленные на прогнозирование отказов и отказовых ситуаций при исполнении программы. 2. Методический анализ структурной сложности программных модулей и их взаимо- связей для решения проблемы тестирования и поддержки модулей в работоспо- собном состоянии, а также минимизации информационных потоков между моду- лями. 3. Измерения производительности программного обеспечения, повышения его эф- фективности, а также выполнение финансовых расчетов затрат машинных ре- сурсов. 4. Исследования метрических свойств транслирующих систем, нацеленные на разви- тие языковых средств программирования и повышение качества трансляции. 5. Измерения трудности восприятия программных текстов, направленные на оценку психологических факторов, существенных для модификации и сопровождения программ. 6. Метрический анализ производительности труда программистов для более точного прогнозирования сроков создания программ и планирования работ по созданию программных комплексов. 7. Получение обобщенных характеристик качества программ по ряду критериев. Метрики сложности программ можно разделить на два класса: статические и динами- ческие. Вычисление статических метрик основано на статическом анализе программ. Эти метрики отражают измерение таких факторов, как размер программы, организация данных и управляющая структура программы, и в силу этого их можно разделить на четыре типа: объемные, топологические, метрики потока данных и комплексные. Объемные меры оценивают сложность программ, исходя из чисто количественных объемных характеристик, таких как размер исполняемого кода, число строк в про- грамме, число модулей и т. д. Основными здесь являются меры Холстеда. Топологические меры основаны на анализе структуры управления программы в виде управляющего графа или какой-либо графовой модели, причем в расчет берутся именно топологические характеристики. Метрики потока данных основаны на анализе структуры информационных связей в программе. Комплексные (или гибридные) метрики обычно пытаются устранить недостатки мер, основанных на одном каком-то индикаторе, путем учета разных аспектов сложности, измеряемых разными индикаторами. 10.4.2. Цикломатическая мера Мак-Кейба Цикломатическая мера сложности программы — исторически первая из топологиче- ских мер. В ее основе лежит идея оценки сложности программы по числу так назы-
780 Часть II. Применение графов и граф-моделей ваемых базисных путей в управляющем графе программы, т. е. таких путей, комби- нируя которые можно получить всевозможные пути из входа графа в выход. Оценка числа таких путей получается на основе г/икломатического числа орграфа, под кото- рым подразумевается величина X(G) = M(G) - n(G) +• p(G), где M(G) — число дуг, n(G) — число вершин и p(G) — число компонент связности орграфа G. Заметим, что X(G), определенное таким образом, есть в точности определение цикломатического числа неориентированного графа, получаемого из орграфа G заменой всех дуг ребра- ми и ликвидацией кратных ребер, возникающих при этом. Второе замечание касается величины p(G), которая в случае управляющего графа всегда равна единице, p(G) = 1. Поэтому, начиная с этого момента, будем считать, что X(G) = A7(G) — n(G) + I. Определение цикломатического числа орграфа через цикломатическое число соот- ветствующего неориентированного графа имеет своим следствием то, что в орграфе не различаются фрагменты, моделирующие условный оператор и цикл (рис. 10.20). Рис. 10.20. Фрагменты, имеющие одно и то же цикломатическое число а — условный оператор, б — цикл Цикломатической сложностью программы Р с управляющим графом G называется величина v(P), определяемая формулой v(P) = Z.(G) + 1 = M(G) - n(G) + 2. Нетрудно увидеть, что число базисных путей в G в точности равно Z(G) + 1 (рис. 10.21). Рис. 10.21. Уграф и его базисные пути
Глава 10 Потоковый анализ программ 781 Цикломатическая сложность программы, содержащей вызовы подпрограмм, опреде- ляется как сумма цикломатических сложностей программы и вызываемых подпро- грамм. Цикломатическую сложность можно вычислять без построения уграфа на основе следующего свойства. А. Цикломатическая сложность программы равна числу предикатов плюс единица. К достоинствам никломатической меры сложности относятся: □ легкая вычисляемость и повторяемость результатов вычислений; П наглядность и содержательная интерпретируемость; □ возможность сравнения программ; □ возможность использования для разработки стратегий тестирования программ; □ возможность оценки качества груда программистов. Большинство авторов, упоминая в своих работах или анализируя цикломатическую сложность, согласны с правильностью выводов Мак-Кейба об ее адекватности интуи- тивному пониманию сложности, о ненадежности программ, чья цикломатическая сложность превышает 10, о легкости применения этой меры. Однако эти же авторы единодушно предупреждают о недопустимости однозначных выводов при сравнении двух конкретных программ, основываясь только на этой мере, т. к. она отражает лишь одну сторону программы и не учитывает другие. К недостаткам меры Мак-Кейба относятся: □ нечувстительность к размеру программы; □ относительная нечувствительность к изменению структуры; П отсутствие корреляции со структурированностью программ (цикломатическая сложность может быть ниже у неструктурированной программы по сравнению с ее структурированным вариантом); Рис 10.22. Уграфы Gi G2 и G3 с цикломатической сложностью 3
782 Часть II. Применение графов и граф-моделей Рис. 10.23. Уграфы Ga, Gs и Gg с цикломатической сложностью 3 □ отсутствие различия между конструкциями IF и конструкциями с циклами (см. рис. 10.20); □ отсутствие чувствительности к вложенности циклов. Последние два недостатка иллюстрируются на рис. 10.22 и 10.23. Цикломатическая сложность всех графов, изображенных на этих рисунках, одинакова и равна 3. 10.4.3. Другие меры сложности, основанные на уграфе Критика в адрес цикломатической меры и желание охватить другие характеристики программ привели к появлению новых мер, часть которых является вариантами меры Мак-Кейба. Функциональная мера сложности Харрисона—Мейджела Данная мера учитывает уровень вложенности предикатных конструкций и протяжен- ность программы. Она предусматривает приписывание каждой вершине своей собст- венной сложности, определяемой сложностью оператора, изображаемого вершиной. Эта начальная (первичная) сложность может вычисляться любым способом, включая использование мер Холстеда. Выделим для каждой предикатной вершины подграф, порожденный всеми теми вершинами, которые являются концами исходящих из нее дуг, вершинами, которые достижимы из каждой такой вершины (нижняя граница подграфа), а также вершинами, лежащими на путях из предикатной вершины в ка- кую-нибудь нижнюю границу. Этот подграф называется сферой влияния предикатной вершины. Приведенной сложностью предикатной вершины называется сумма на- чальных или приведенных сложностей вершин, входящих в ее сферу влияния, плюс первичная сложность самой предикатной вершины. Функциональной мерой программы называется сумма приведенных сложностей всех вершин управляющего графа. Если первичные сложности вершин не отражают действительной сложности соответ- ствующих операторов, то функциональная сложность в том виде, как она была опре-
Глава 10. Потоковый анализ программ 763 делена, может быть источником заблуждений. Во избежание этого вводится понятие функционального отношения. Функциональным отношением называется отношение числа вершин в управляющем графе к его функциональной сложности, при этом в число вершин включаются толь- ко те вершины, первичная сложность которых не меньше единицы. Ясно, что величина функционального отношения уменьшается с ростом сложности программы. Например, программа с функциональным отношением, меньшим 0,4, должна рассматриваться как достаточно сложная. Мера Пивоварского Эта мера преследует цель учесть в оценке сложности программ различия не только между последовательно вложенными управляющими конструкциями, но и между структурированными и неструктурированными программами. Назовем модифицированной цикломатической сложностью меру, вычисляемую так же, как и цикломатическая, но с одним отличием: оператор CASE с и выходами рас- сматривается как один логический оператор, а не как п - 1 операторов Мерой Пивоварского N(G) называется величина W(G)=v* (С)+У/- , где v*(G)— мо- I дифицированная цикломатическая сложность, Р,— глубина вложенности /-й преди- катной вершины. Для подсчета глубины вложенности предикатных вершин используется сформулиро- ванное понятие сферы влияния. Под глубиной вложенности понимается число всех сфер влияния, которые либо полностью содержатся в сфере влияния рассматривае- мой вершины, либо пересекаются с ней. Заметим, что глубина вложенности увеличи- вается не за счет вложенности предикатов, а за счет вложенности сфер влияния пре- дикатов. Значения функционального отношения и меры Пивоварского для графов на рис. 10.23 и 10.24 приведены в табл. 10.1. Таблица 10.1. Функциональное отношение и мера Пивоварского Граф v(G) Функциональное отношение W(G) G5 3 0,6 3 G. 3 0,5 3 G, 3 0,56 4 g4 3 0,4 4 g2 3 0,57 5 G6 3 0,5 5
784 Часть II. Применение графов и граф-моделей Тестирующая мера Назовем меру т(Р) сложности программ собственной мерой, если она удовлетворяет следующим трем аксиомам: □ m({S,;S2; ..;S„})>Sw(Si); □ 2(w(5|) + w(S2)) > m(if P then S, else S2) > m(St) + w(S2); □ 2m(S) > m(while P do S) > m(S). Выполнение неравенств в левых частях аксиом требуется только для достаточно больших A/(S) Легко убедиться, что цикломатическая мера сложности Мак-Кейба является собст- венной мерой. Тестирующей мерой р называется мера сложности, удовлетворяющая следующим условиям: □ мера сложности простого оператора равна 1; a p({5i;S2;...;S„}) = Zp(S,); □ p(if Р then S|\else S2) = 2 max(p(.S’i), p(S2)); П p(while P do S) = 2p(S). В отличие от цикломатической меры тестирующая мера программы с вложенными управляющими конструкциями значительно больше тестирующей меры программы с тем же числом управляющих конструкций, но расположенных последовательно. Кроме того, данная мера учитывает также протяженность программы. К тестирующей мере в идеологическом плане близки следующие меры, мера на осно- ве регулярных выражений и характеристический полином. Мера на основе регулярных выражений Мейджелу принадлежит идея использовать в качестве меры сложности программы число символов (операндов, операторов и скобок) в минимальном по числу скобок регулярном выражении, построенном для управляющего графа программы. Характеристический полином PCN Пусть G управляющий граф программы, и пусть для него построена иерархия вло- женных подграфов с одним входом и одним выходом в виде диаграммы, в которой точки на (к+ 1)-м уровне изображают отдельные вершины и вложенные структуры подграфа, размещенного на к-м уровне. При вычислении характеристического поли- нома каждой вершине в диаграмме сопоставляется число CN = 1. Для структуры S последовательного типа на к-м уровне характеристическое число CN определяется как произведение характеристических чисел вложенных в 5 структур и вершин на (к+ 1)-м уровне. Для структуры S типа выбора CN определяется как сумма характе- ристических чисел вложенных в S структур и вершин не более чем с одной исходя- щей дугой, увеличенная на 1 в случае конструкции if - then. Для циклической струк- туры C7V определяется как произведение переменной с на CW непосредственно вло-
Глава 10. Потоковый анализ программ 785 женных структур и содержащихся вершин (не более чем с одной исходящей дугой) или на CN + 1 в случае цикла while - do. Тогда характеристическим полиномом PCN называется характеристическое число на самом верхнем (нулевом) уровне. Вариантом данной меры служит характеристический полином от двух переменных а и Ь. Для графов, изображенных на рис. 10.24 и 10.25, последние три меры, а также меры Мак-Кейба и Пивоварского представлены в табл. 10.2. Рис. 10.24. Уграфы Ge и Gg Рис. 10.25. Уграфы Gw и Gn Как можно заметить, все эти меры отличаются от меры Мак-Кейба чувствитель- ностью к вложенности управляющих конструкций и к протяженности программ. Кроме того, функциональная мера сложности позволяет проводить редукцию графа путем замены некоторых участков программы одной вершиной, "первичная слож- ность" которой может быть измерена любой подходящей мерой, не исключая и меру Холстеда.
786 Часть II. Применение графов и граф-моделей К недостаткам этих мер следует отнести возрастающий уровень трудоемкости вычис- лений и появление опасности неповторимости результатов. Последнее особенно каса- ется функциональной меры и меры Пивоварского. Таблица 10.2. Различные топологические меры Граф v(G) Регулярное выражение Мера Мейджела PCN PCN N(G) g7 2 A(B + C)D 7 2 2 2 g8 3 A(B + C)D{E + F)G 13 4 4 3 g9 3 AB(AB)*D(CD)* 14 c2 2 a 3 Gio 3 ABC(BC)*D(ABC 21 c2 Ab 4 G„ 4 AB(C + DE(DE)*)F (B(C + DE(DE)*)F* 30 c2 + c ab + a 5 10.4.4. Декомпозиция уграфов Одной из проблем, возникающих в связи с оценкой сложности программ, является проблема декомпозиции уграфа на так называемые подуграфы, под которой понима- ется разложение уграфа на фрагменты, каждый из которых имеет один вход и один выход. Уграф с множеством вершин К, множеством дуг Е, входом 5 и выходом Т будем обозначать через (G, s, t), где G— ориентированный граф с множеством вершин E(G) = V и множеством дуг E(G) = G Для уграфа (G. s, f) будем обозначать через Г/(С) множество E(G) \{t}. Уграф S = (Н, х,у) называется подуграфом уграфа F = (G, s, t), если х *у, х является единственной начальной вершиной Н в F, а у — единственной выходной вершиной Н bG. Легко увидеть, что любой подуграф S = (H, х,у) уграфа F однозначно определяется своей входной вершиной х, выходной вершиной у и множеством внутренних вершин. Кроме того, в любом подуграфе 5 = (И, х, у) уграфа F вершина х является единствен- ной входной вершиной Н в F, из х достижима любая другая вершина S, а вершина у достижима из любой другой вершины S. Заметим, кстати, что выходная вершина у некоторого фрагмента уграфа в общем слу- чае может также быть и его входной вершиной Для иллюстрации этого момента рас- смотрим уграф Е на рис. 10.27. В нем подграф с начальной вершиной е, конечной вершиной h и множеством вершин {e,f h} имеет две входные вершины е, h
Глава 10. Потоковый анализ программ 787 Рис. 10.26. Управляющий граф Е Пусть F = (G, s, I) — уграф. Напомним, что вершина х доминирует над вершиной у (обозначение х <у) тогда и только тогда, когда любой путь в G из s в / проходит через х. Аналогично, у постдоминирует над х (обозначение х < ( у) тогда и только тогда, когда любой путь в G из х в t содержит у. Отношения <., и <, являются частичными порядками на И(С7), и результирующие частично упорядоченные множества представляют собой ордеревья, называемые до- минаторным деревом Ts и постдоминаторным деревом Т,. Для уграфа Е доминатор- ное дерево Д изображено на рис 10.27, а постдоминаторное дерево Т,— на рис. Ю 28 Для удобства изложения будем обозначать для любой вершины х 6 T(G) максималь- ное поддерево дерева Д, состоящее из вершин, достижимых из х в Д, через Д(х). Со- ответствующее множество вершин поддерева Д(х) будем обозначать через В(х). Имеется связь между подуграфами и деревом доминирования данного уграфа. В ча- стности, для любого подуграфа 5 = (И, х, у) уграфа F = (G, s, f) множество H(G) со- стоит из вершин некоторого поддерева Д. А. Пусть S = (Н, х, у) — подуграф уграфа F= (G, s, t). Тогда Vt(G) с В(х). Рассмотрим уграф Е на рис. 10.26 и его доминаторное дерево Д. Пусть S\ = (ГЦ, d, Л) и S2 = (Н2, d. s) — подуграфы с вершинами d, e,f g, h и d, e,f g, h, i, s, соответствен-
788 Часть II. Применение графов и граф-моделей но. Из рис. 10.27 видно, что поддерево Tx(d) включает все вершины //| (включая И) так же, как и все вершины /Л, исключая л. Заметим, что Н\ содержит в точности те вершины из Тх(сГ), которые не принадлежат ТХ(И), и. кроме того, вершину /?, т. е. И(//|) = - В(Л)] о {Л}. Что касается S2- то Н2 содержит все вершины из и поэтому И(//2) = B(d) и {5}. Рис. 10.27. Доминаторное дерево Рис. 10.28. Постдоминаторное дерево
Глава 10. Потоковый анализ программ 789 Б. Пусть w — произвольная вершина в (G, s, t). Если Р — путь в G из и в v, где и g B(w) « v е B(w), то Р содержит w. В. Пусть S = (Н, х, у) — подуграф уграфа F = (G, s, t). Тогда: □ если х < .,у, то V(H) = [В(х) - 7?(у)] U {у}; □ еслих=£ sy, то У(П) = В(х) о {у}. Свойство В говорит о том, что множество вершин любого подуграфа S уграфа F = (G, х, у) может быть определено (и единственным образом) из дерева Т, при усло- вии, что мы знаем входную и выходную вершины S. Это делает естественным внима- ние к нахождению пар х, у, где х и у — входная и выходная вершины некоторого по- дуграфа. С этой целью будем сопоставлять с каждой вершиной х уграфа последова- тельность вершин, каждая из которых есть выходная вершина некоторого подуграфа с входной вершиной х. Г. Если S = (Н, х, у) — подуграф уграфа F = (G, s, I), то w< ,у для всех вершин м из Н. Из этого свойства следует, что отношение х < ,у имеет место для входной верши- ны х и выходной вершины у любого подуграфа уграфа F. Пусть х— вершина в F=(G, s,/), и пусть (уь ...,ук)— путь в Т, из x=yi в 1=ук- Обозначим последова- тельность (уь ...,ук) через Z(x). Очевидно, что Z(x) состоит из постдоминаторов вер- шины х и определяется однозначно для каждой вершины х из F. Из свойства Г также следует, что выходная вершина у любого подуграфа S = (77, х, у) есть элемент Z(x). Более того, S содержит все вершины, которые предшествуют у в Z(x). Д. Пусть S=(H, х,у) — подуграф F= (G, s, I), и пусть Z(x) = (уь ...,у*). Тогда суще- ствует г, 1 < г < к, такое, чтоуг—у. Более того, у, е И(/7) для i = 1,2, ..., г. Согласно свойству A, И/G) с В(х) справедливо для любого подуграфа S = (77, х, у) уграфа F. Таким образом, в соответствии со свойством Д, если Z(x) = (уь ...,Уа) и у, е В(х) для некоторого i < к, то ни одна вершина^, i<j < к, не может быть выход- ной вершиной подуграфа с входной вершиной х. Этот факт позволяет уточнить опре- деление множества потенциальных выходных вершин подуграфов с заданной вход- ной вершиной. Е. Пусть х— вершина из F=(G, s, Г), и пусть Z(x) = (уь ..., у*). Тогда существу- ет такое г, 1 < г < к, что Z?(x) n { yi,..., у*} = {у, | i < г}. Более того, (уь ..., у*) есть путь в Т, Свойство Е устанавливает связь между обоими деревьями доминирования уграфа F. Из него следует, что для любой последовательности Z(x) = (уь..., у*) существует такое г < к, что (yi, ...,уг) представляет пути из х в уг как в Т„ так и в Ts(x), в то время как оставшиеся вершины Z(x) (когда г < к) не принадлежат Тг(х). Пусть х— вершина из F=(G,s,t). Пусть Z(x) = (Уь —,У*), и пусть г определено как в свойстве Е. Определим последовательность Z'(x) как подпоследовательность (у,,у2, — ,Ур) последовательности Z(x), где р = г + 1, если г < к, и р = г в противном случае. Другими словами, если В(х) не включает в себя всех элементов из Z(x), io ур
790 Часть II. Применение графов и граф-моделей будет первым элементом в Z(x), который не принадлежит В(х), в противном случае Z'(x) = Z(x). Ж. Если S = (/7, х, у) — подуграф уграфа F = (G, s, t), mo у есть элемент Z,(x). Рассмотрим уграф Е и его деревья доминирования, представленные на рис. 10.26— 10.28. Из дерева 7} получаем Z(f) = (f,e, h, i, s,j, nt, n, f), но Z'(f) = (f e), t. к./'есть лист дерева T,. Таким образом, Е может иметь (и фактически имеет) самое большее один подуграф с входной вершиной/.’ Рассматривая вершину Ь, определим Z'(h) = (b, с, s). Заметим, что (Ь, с) есть путь в Ts и что существуют подуграфы уграфа Е с входной вершиной b и выходными вершинами с и а, соответственно. Теперь рассмотрим собственно определение подуграфов некоторого уграфа. Пусть х — вершина уграфа F = (G, s,f) и у — любая вершина из Z'(x). Пусть Н — под- граф графа G такой, что V(H) = [В(х) - В(у)] U {у}, если х < ,у, V(H) = В(х)U {у}, если х /,у, и А{Н) = {(г/, v) е Z(G) | u, v е Е(/7) & и у}. Тогда Н называется /подграфом, индуцированным парой х, у, и обозначается G(x, у). Следующее свойство есть прямое следствие свойств В и Ж. 3. Если S = (Н, х, у) — подуграф уграфа F = (G, s, t), то Н = G(x, у). Обратное утверждение в общем случае неверно. Это становится ясным, если рас- смотреть, например, уграф Е на рис. 10.26 и его /подграф, индуцированный парой /, т. Чтобы определить, является или нет /-подграф подуграфом, недостаточно рассмот- реть деревья доминирования исходного уграфа, нужно проверить его дуги. Рассмот- рим, например, уграф, получаемый из Е (см. рис. 10.26) удалением дуги (п, к). Легко увидеть, что деревья доминирования обоих (исходного и нового) уграфов — те же самые, но новый имеет подуграф с входной вершиной j и выходной вершиной т в противоположность Е. Достаточные условия для /-подграфа быть подуграфом указываются следующим свойством. И. Пусть G(x, у) — f-подграф уграфа F = (G, s, f) такой, что х * у. Тогда (G(x, у), х, у) есть подуграф F тогда и только тогда, когда выполняются следующие условия: □ если w — входная вершина G(x, у) в F, то либо w = х, либо ш = у; □ если w — выходная вершина G(x, у) в F, то w = у. Определим, наконец, такое упорядочение вершин уграфа, которое может быть ис- пользовано для непосредственного определения /-подграфов. f-порядком для F - (G, я, f) называется порядок посещения вершин во время обхода (в постпорядке) дерева Т„, определяемый рекурсивно следующим образом: 1. Посетить корень г поддерева Т (вначале Т= Ts). 2. Если Т имеет больше одной вершины, то применяем последовательно шаги 1 и 2 к каждому из максимальных деревьев дерева Т с корнями хь ..., х*, где х(, ...,х*
Глава 10. Потоковый анализ программ 791 суть сыновья гв Т, причем они упорядочиваются по правилу: если существует но- мер i < к такой, что х, является сыном г в Т, (непосредственным постдоминатором г), то поддерево с корнем х/ должно проходиться последним. Очевидно, /-порядок определяется неединственным способом. Пусть < f обозначает /^порядок на F = (G, s, t) и пусть х, у— произвольные вершины из G. Тогда будем использовать обозначение [х,у] для множества {we K(G)| x<fw & w<fy} и BOUND(x) для максимального (относительно < элемента в В(х). К. Пусть f-порядок определен на F = (G, s, t). Если G(x, у) — произвольный f-подграф уграфа F, то: □ K(G(x, у)) = [х, у], если х < sy; □ K(G(x, у)) = [х, BOUNDfx)] и {у}, еслих &,у. Это свойство дает способ прямого определения вершин /-подграфов на базе /-порядка (и доминирования). 10.5. Потоковый анализ программ Анализ потока данных (как и потоковый анализ в целом) естественным образом раз- деляется на внутрипроцедурный и межпроцедурный анализы. Разные приложения связаны либо с низким (операторным) уровнем анализа, либо с более высоким уров- нем, например, с анализом на уровне модулей или параллельных ветвей. Применяе- мая при разных видах анализа техника не различается существенно, но в них различны объекты, подвергающиеся анализу, а также они могут различаться по типу решаемых задач и/или охвату структурных свойств анализируемой программы. Внутрипроце- дурный анализ имеет дело с операторами или линейными участками одной процеду- ры и с передачами управления между ними. Межпроцедурный анализ рассматривает процедуры программы и отношение обращения одной процедуры к другой. В процессе анализа потока данных как бы происходит одновременное исполнение всех программ, моделируемых схемой, над всеми значениями из некоторой символи- ческой и сильно упрощенной версии области ее реальных данных. Всю базисную ин- формацию о программах, извлекаемую при анализе потока данных в моделируемых их схемах, можно разделить на две группы: свойства исполнений и свойства состояний. 10.5.1. Задача анализа потока данных Свойство исполнений имеет вид утверждения о том, что возможно такое исполнение одной из программ, моделируемых схемой, при котором выполняется нечто (напри- мер, реализуется информационная связь между указанными операторами или оказы- ваются несовместимыми по памяти две указанные переменные и т. д.). По существу, задача извлечения свойств исполнений формулируется как задача доказательства су- ществования пути определенного вида в схеме (управляющем графе схемы). Во мно- гих случаях оказывается достаточным рассмотреть только простые пути по уграфу,
792 Часть II. Применение графов и граф-моделей и поэтому основой большинства методов анализа свойств исполнений являются алго- ритмы транзитивного замыкания орграфа, рассмотренные ранее (см. разд 3.2). Задача нахождения свойств состояний (или, как еще говорят, глобального потоко- вого анализа или абстрактной интерпретации) представляет собой задачу построе- ния набора определенного вида утверждений, отнесенных ко всем точкам схемы и дающих достоверную информацию о поведении в соответствующих точках любой программы, моделируемой данной схемой. Каждое свойство состояний имеет вид утверждения о том, что при любом исполнении каждой моделируемой программы в данной ее точке выполняется нечто (например имеется определенное соотношение между значениями переменных или данное выражение является избыточным, т. е. операнды выражения сохранили свои значения после последнего вычисления выра- жения). Выделяют две группы задач о нахождении свойств состояний: прямые и обратные. Свойство состояний в некоторый момент выполнения схемы в прямой задаче зависит только от свойств состояний в моменты выполнения, предшествующие данному, а в обратной — только от свойств состояний в моменты выполнения, следующие за дан- ным. Метод решения таких задач, получивший название метод разметки, связан с их формулированием в виде уравнений, описывающих изменения свойств состояний на каждом из путей по схеме. Решение задачи анализа свойств состояний имеет вид раз- метки, которая сопоставляет некоторое значение с каждой вершиной уграфа; этим значением может быть множество фактов, отношение или множество утверждений, которое является пересечением соответствующих множеств, получаемых при движе- нии по направлению дуг по всем путям до данной вершины от начальной вершины в случае прямой задачи (соответственно против направления дуг от конечной вершины до данной в случае обратной задачи). Особенно эффективно применение этого метода в случае, когда свойства состояний, различаемые в формулировке задачи, образуют конечное множество, что позволяет эффективно реализовать пометки, описывающие свойство состояний в разных точках программы, в виде шкал, и находить точное решение. Когда точное решение не мо- жет быть вычислено, обычно методы анализа свойств состояний работают с некото- рой полурешеткой свойств состояний (с заданным на свойствах отношением аппрок- симации) и нацелены на поиск наилучшего приближенного решения (наилучшей ап- проксимации). Как правило, существует целый ряд моделей аппроксимирующих решеток для одной и той же заданной задачи анализа свойств, которые могут различаться точностью по- лучаемого решения и сложностью его нахождения. Обычно все они являются упоря- доченными подмножествами некоторой одной естественной (но часто трудной для решения) полурешетки. Однако не для всякой задачи существует достаточно естест- венная формализация с помощью решетки. В ряде случаев для задачи можно привес- ти несколько неразрешимых формализаций в виде решеток или задача такова, что вообще нет ее естественных формализаций, поскольку' концепция решетки сама по себе представляется не естественной для задачи как это имеет место для втягивания констант. Вместе с тем, можно формально определить понятие оптимальной аппрок- симирующей схемы, которая, однако, может быть не практичной Можно также пока-
Глава 10. Потоковый анализ программ 793 зать, что ряд задач анализа потока данных, включающий проверку границ массивов, определение знака значений переменных и втягивание констант, может быть естест- венным образом представлен в виде различных подрешеток одной и той же решетки свойств программы о возможных значениях переменных целого типа. Точно так же как менее точная информация может потребовать меньших затрат, так и более точная информация иногда может быть получена с одновременным увеличени- ем сложности. Часто возможно осуществить уточнения результатов анализа свойств состояний, комбинируя две решетки на управляющем графе, одной из которых (ос- новной) является исходная решетка задачи анализа свойств, а другой - решетка множеств условий, которые определяют, когда информация распространяется по ду- гам управляющего графа. Для такой постановки используется термин задачи квали- фицированных путей. В ее рамках получается более точные аппроксимации по отно- шению к потоку информации периода исполнения даже для классических проблем, однако с использованием существенно более большой схемы по размеру. Рассмотрение двух разных формулировок одной и той же задачи анализа потока дан- ных позволяет ставить вопрос о корректности одной из них по отношению к другой, когда путем "разбиения" или "абстракции" осуществлен переход от одного множест- ва состояний (управления, памяти) к поддающимся более эффективной обработке классам их эквивалентности. Например, разбиение может включать игнорирование адресов переменных в памяти, абстрагирование от конкретных целых значений, хра- нимых в переменной, и игнорирование многих уровней ссылок по указателям. Вместе с тем, аппроксимирующая семантика должна отражать лежащую в основе формаль- ную семантику; это означает, что состояния в аппроксимирующей семантике должны формировать полурешетку, а аппроксимация должна быть безопасным отображением (т. е аппроксимация некоторого состояния и применение функции преобразования должны давать некоторое аппроксимирующее состояние, которое является безопас- ной оценкой реального результирующего состояния). Именно поэтому определение программных свойств применением аппроксимирующей семантики часто называю! абстрактной семантикой. Для решения задачи анализа свойств обычно рассматривается и решается множество уравнений, которые устанавливают связь между значением разметки для каждой вершины со значениями разметки в других вершинах, семантическими функциями вершин (или дуг), дополнительной информацией, известной для начальной (или ко- нечной) вершины, и, возможно, некоторыми глобальными константами. Вершины, появляющиеся в уравнении для некоторой вершины, почти всегда образуют некото- рое подмножество ее соседей: обычно это либо все ее предшественники в уграфе в случае прямой задачи, либо все ее преемники в случае обратной задачи. Методы решения направлены на поиск решения указанной системы уравнений, которое явля- ется наибольшим (т. е. наибольшей неподвижной точкой); оно и рассматривается в качестве наилучшего решения задачи анализа свойств. Использование пересечения в задачах анализа свойств состояний в некотором смысле не по существу и в силу двойственности все рассуждения могли бы быть произведены в терминах полурешеток объединения. В полурешетке объединения вместо терминов "пересечение по всем путям", "максимальная неподвижная точка", "наибольшее ре-
794 Часть II. Применение графов и граф-моделей шение" должны использоваться термины "объединение по всем путям", "минималь- ная неподвижная точка”, "наименьшее решение" соответственно. Иногда схемы свойств состояний классифицируются в пространстве векторов, обра- зующих множество {пересечение, объединение} х {прямая, обратная} х {максималь- ное решение, минимальное решение}. Существуют алгоритмы, которые используют различные комбинации векторов на различных фазах своего выполнения. 10.5.2. Метод разметки Любая прямая задача о свойствах состояний схемы при ее формулировании для схе- мы, полученной из исходной изменением ориентации дуг управляющих связей, ста- новится обратной, а обратная —- прямой. Поэтому, учитывая то, что для большинства интересных свойств, формулировка в виде прямой задачи оказывается более естест- венной, мы ограничимся рассмотрением применения метода разметки для прямых задач. Рассматриваются полурешетка свойств L — множество пометок с отношением по- рядка £, не содержащее бесконечных цепей и являющееся полурешеткой с нулем 0 и 1 относительно операции пересечения П— и F— множество так называемых преобразователей пометок (свойств), которое состоит из монотонных функций ft L —> L и является замкнутым относительно композиции функций (т. е./'о g е L для любых/и g из L), а также содержит тождественную функцию е (т. е. е(а) = а для всех а е L) и для любого a е L такую функцию/е L, что а =Д0). Схемой свойств состояний (схемой с разметкой) л называется пятерка л = (G, L, F, М, <70), где G— уграф, L — полурешетка свойств, F— множество преоб- разователей пометок из L, аое L— начальная пометка, М— функция, сопоставляю- щая каждой дуге и уграфа G функцию эффекта дуги М(и) е F, обозначаемую через fu, схема л хорошо определена, если существуют алгоритмы, позволяющие для любых a, b е Lvtfe F вычислять элементы а П b wfla). В дальнейшем будем рассматривать только хорошо определенные схемы с разметками. Задача анализа схемы свойств состояний л формулируется как задача нахождения так называемой полной разметки схемы л — такой разметки A tX-*L, что А(р) = Г1{Ж°о) ' уеПУТЬ(р)} для любой вершины р е X, где ПУТЬ(р) — множество путей по л от р0 до р, а для пути у = (qx, щ, q2, -, и„ qr) функция эффекта пути f определяется как композиция f °...°/И|, если г > 1, и как тождественная функция е, если г = 1. По отношению к конкретной оптимизации некоторой крупноблочной схемы а (см. разд. J 1.3) введенные понятия имеют следующий содержательный смысл. Поня- тие пометки формализует интересующее нас свойство (множество) состояний выпол- нений схемы a, L — множество всех различных (с точки зрения данной оптимизации) свойств состояний, на котором задано отношение аппроксимации: для любых a, beL, если а £ Ь, то а является корректной аппроксимацией свойства Ь, т. е. множество со- стояний выполнения, описанных пометкой а, содержит соответствующее множество для пометки Ь. Операция пересечения П, заданная на L, позволяет по любым двум
Гпава 10. Потоковый анализ программ 795 a, beL находить такое свойство с — а П Ь, что с является в L наилучшей аппроксима- цией свойства, описывающего объединение свойств состояний, связанных с а и Ь. Например, L может состоять из предикатов на множестве состояний памяти, и тогда для любых о, b&L выполняется следующее: если а £ Ь, то b -> о; если с = а П Ь, то a v b —» с, причем для любого такого предиката d, что a v b —> d, либо d не принад- лежит L, либо с -> d. Рассматриваются формальные выполнения схемы ос. Для каждого оператора S и каж- дой исходящей из него дуги и предполагается, что независимо от свойства состояния, с которым мы пришли к S, нормально завершается формальное выполнение операто- ра S, приводящее к переходу по дуге и, и его семантика описывается функцией f,. Та- ким образом, множество всех формальных выполнений определяется множеством всех путей у по а от ее начальной вершины, а/у — семантический эффект формально- го выполнения у. Далее, ад— это свойство состояний, с которых а начинает свои формальные выполнения, а полная разметка для каждого оператора S задает то свой- ство из L, которое является наилучшей аппроксимацией множества состояний фор- мальных выполнений схемы а на момент достижения оператора S. Рассмотрим в качестве примера задачу нахождения отношения обязательного пред- шествования для сводимого уграфа G (см. разд. 4.3.7). Она может быть сформулиро- вана как задача анализа схемы свойств состояний л = (G, L, F, М, а0), в которой L — множество шкал длины П — операция покомпонентной конъюнкции ®; F состоит из функций fia) = а® b для каждого b е L, где ® — операция покомпонентной дизъ- юнкции; а для любой дуги и функция f/Д) равна а © (О'-'Д.О"'1), где 1=И(нач(иУ). Другими словами, каждая пометка а = А(р) задает следующее свойство состояний выполнений, возникающих непосредственно перед началом выполнения р: для любо- го /е[1:и] значение /-го элемента пометки а равно 1 в том и только в том случае, ко- гда при любом формальном выполнении схемы оператор с номером i выполняется до момента начала выполнения оператора р. А. Не существует алгоритма, осуществляющего построение полной разметки для любой хорошо определенной схемы с разметкой. Поскольку полная разметка не всегда может быть найдена, при анализе программ часто ограничиваются нахождением некоторой корректной разметки. Разметка В: %—> L называется корректной, если для любых р е X и у е ПУТЬ(р) выполняется В(р) ^.А(«о)- Отношение частичного порядка £ на множестве пометок L задает отношение частич- ного порядка £ на множестве разметок схемы л: R\ £ Л2, если для любой вершины р е X выполняется Ri(p) £ R^Cp)- Б. Для полной разметки А и корректной разметки В справедливо В А. Разметка В схемы л называется стационарной, если В(р) = а0 и В(р) — = \}{/и(В(нач(и))): и & ЗАХОД(р)} при р^р0. Такая стационарная разметка R, что В^ R для любой стационарной разметки В, называется насыщающей. Такая коррект- ная R, что В £ R для любой стационарной разметки, называется хорошей.
796 Часть II. Применение графов и граф-моделей В. Для любой схемы я насыщающая разметка существует и является хорошей. Г. Если F содержит только дистрибутивные функции, то насыщающая разметка схемы является полной. Д. Если F содержит недистрибутивные функции, то найдутся такие схема и ее вершина р, что В(р) Р А(р), где В и А — насыщающая и полная разметки схемы. Процедуры нахождения насыщающей разметки разделяются на три основных класса. Два из них, называемые методами элиминации и итерации, основываются на нахож- дении решения системы уравнений для разметки: *(р)= а0, еслир=р() П/«<Л1''ОЧ(И)), ес™Р*Ро иеЗАХОД(р) Итеративные процедуры начинают вычисление с "безопасной" аппроксимации раз- метки X, где Х(ро) = а0 и Х(р) = 1 для всех р ф р0, и неоднократно осуществляют пере- вычисления текущего состояния разметки X. Для этого представляются текущие зна- чения разметки X в правую часть каждого уравнения и вычисляются новые (резуль- тирующие) значения Х(р) для всех р. Процесс повторяется до тех пор, пока не будет найдено решение системы уравнений, это и будет насыщающая разметка. Итеративные процедуры различаются порядком, в котором они вычисляют уравне- ния, а также тем, как используются измененные (уже вычисленные значения) для вы- числения других значений. Элиминационные процедуры аналогичны методу Гаусса. Они используют декомпо- зицию уграфа и редукцию для получения все меньших и меньших систем уравнений, которые затем могут быть разрешены более простым методом. Элиминационные процедуры различаются трансформациями, которые используются для перехода от текущих уграфа и системы уравнений к редуцированным, а также условиями, при которых эти трансформации применимы. Указанные методы обычно эффективно работают на некотором подклассе уграфов (см. разд. 10.5.5). Третий подход к нахождению насыщающей разметки опирается на алгебру путей. Процедура решения, используемая при таком подходе, очень похожа на процедуру решения регулярных выражений между парами вершин помеченного уграфа. Этот подход более близок к методам элиминации, чем к методам итерации, но в отличие от них он не требует существования решетки свойств и не всегда позволяет находить решение системы уравнений. 10.5.3. Примеры задач анализа свойств состояний Константность переменных Переменная х называется константной в операторе S крупноблочной схемы а, если при любой интерпретации I е Qa перед выполнением оператора S переменная х имеет одно и то же значение.
Глава 10. Потоковый анализ программ 797 Задача определения константности переменных для всех операторов схемы а может быть сформулирована в виде задачи анализа схемы свойств л = (G, L, F, М, 0), в кото- рой L = 2Л, где £ = {(х, с) : х е Xa, с е u {D,: I е Qa}}, 0 — пустое множество, 1 = £, П— операция пересечения множеств, F— множество всех монотонных функций из L в L. Для любой дуги и и любого элемента а е L значение f„{a), где/„ = М(и), обла- дает следующим свойством: для любого состояния памяти W, такого что ас {(х, Н'(х)) :х е Ха}, и любой интерпретации / е Qa выполнение оператора S = нач(и) на W при /, завершающееся переходом по дуге и, вычисляет такое состоя- ние памяти W, что/„(о) с {(х, W(x)) : х е Ха]. Оптимизирующее преобразование, базирующееся на информации о константности переменных, получило название втягивание констант. Оно состоит в замене в каж- дом операторе S переменных х на константы с из пар (х, с), образующих пометку опе- ратора £ в полной разметке схемы л, с последующей сверткой констант (т. е заменой константных выражений на их значения) в операторе £. Избыточность выражений Выражение Ф в операторе £ крупноблочной схемы а называется избыточным, если при любой интерпретации / е Qa значение выражения /У(Ф), где W — состояние памяти перед выполнением оператора £. уже вычислялось при выполнении хотя бы одного из операторов, предшествующем данному выполнению оператора £. Задача определения избыточных выражений для всех операторов схемы а может быть сформулирована в виде задачи анализа следующей схемы свойств л = (G, L, F, М, 0). Пусть £= {£ь ..., Ег}, где для любого i е [1 : /•] множество £, состоит из эквивалент- ных относительно Qa выражений, имеющих вхождения в схему а (например, £, мо- жет состоять только из текстуально совпадающих выражений схемы или строиться с учетом алгебраических законов операций, используемых в схеме а, и содержать выражения, не только текстуально совпадающие). Множество пометок L— это 2/;, в котором П— операция пересечения множеств, 0 = 0 и 1 = £. Множество F состоит из всех функций f вида f(ci) = (а и Ь) о с, где Ь,с е £. Для любой дуги и функция /„ = A/(w) имеет вид /,(«) = (а и ПОР,^ с\ НЕУБ,,-, ПОРи состоит из таких £,, что оператор £ = нач(и) при любой интерпретации / е Qa вычисляет некоторое выражение из £,. а НЕУБ,, — из таких £„ что ни одно из выпол- нений оператора £, завершающихся переходом по дуге и, не изменяет значения вы- ражений на £, (например, если £, состоит из выражений, в которые не входят резуль- таты оператора S, то £, е НЕУБ,,). Преобразование по удалению избыточных выражений рассматривает для каждого Е, е Е новую переменную х„ т. е. х,Х А„, и заменяет в каждом операторе S, для кото- рого Е, е £(£), где R — полная разметка схемы л, любое вхождение выражений из Е, на переменную х, и вставляет в каждый оператор S, для которого Е, е- £(£), присваи- вание переменной х, некоторого выражения из £„ вычисляемого в S.
798 Часть И. Применение графов и граф-моделей Типы переменных Говорят, что переменная х перед выполнением оператора S в крупноблочной схеме а имеет тип t, если t — множество всех тех значений, которые переменная х имеет пе- ред выполнением оператора S' в схеме а. Задача определения типов некоторой переменной х для всех операторов схемы а может быть сформулирована в виде задачи анализа следующей схемы свойств л = (G, L, F, М, ао). Пусть в универсальном множестве значений переменных D = о {Dt: 1 е Qa} выделе- но некоторое множество подмножеств L = {7/ Тг,Th ...} (т. е. 7, с D для любого i) в качестве типов значений и введена операция П на L, удовлетворяющие свойст- вам пометок. Предполагается также, что L содержит D и пустое множество и для любых Т и Т из L Т Е Т' только тогда, когда Т^Т'\ F — множество всех монотонных функций из L в L и a0 = D. Для каждой дуги и функция/, = М(и} определяется таким образом, что для любых Т е L, I е Qa и состояния памяти W, если Ж(х) е Т, то вы- полнение оператора S = нач(и) на IV при /, завершающееся переходом по дуге и, при- водит к такому состоянию памяти W', что fu(T) JF(x) е fu(T). Информационное влияние Оператор Si не влияет на значение переменной х в операторе крупноблочной схе- мы а, если при любой интерпретации /еОо перед выполнением оператора S2 пере- менная х не хранит значений, присвоенных ей оператором S/ Задача определения для всех операторов S схемы а тех операторов, которые влияют на х в S, может быть сформулирована в виде задачи анализа схемы свойств л = (G, L, F, М, 0), в которой L = 21', где Е — множество всех операторов из а, П — операция пересечения множеств 0 = 0, 1 = Е, F— множество всех функций /вида /а) = (а и fc) р с, где b,c & L. Для любой дуги и функция / = Л/(н) имеет вид fu(a) = (а и М'и) гл Мги, где м\ равно {S}, если существует выполнение оператора 8 = нач(и), завершающееся переходом по дуге и и вычисляющее переменную х, и равно 0 в противном случае, а Мги — множество, состоящее из S и всех тех операто- ров, влияние которых на х не экранируется хотя бы при одном выполнении S, завер- шающемся переходом по дуге и (в частности, если х — обязательный результат опе- ратора S, то Мги = {£}). Таким образом, если оператор Si не содержится в пометке, сопоставленной оператору S2 полной разметкой схемы л, то гарантируется отсутствие информационной связи между операторами Si и S2 по переменной х. 10.5.4. Алгоритм нахождения стационарной разметки Рассмотрим итеративные алгоритмы нахождения стационарной разметки для случая, когда L описывает множество всех подмножеств некоторого конечного множества Е,
Глава 10. Потоковый анализ программ 799 операция П является операцией пересечения двух подмножеств Е, а каждая функция f из Е представима в виде/(х)= (х о £() гз Е2, где £ь £2 — подмножества множества £. Большинство задач анализа свойств состояний, возникающих в традиционных реали- зациях глобальных оптимизаций, формулируется, например, в виде схемы свойств для определения избыточных выражений или обязательных . предшественников (см. разд. 10.5.3). Будем предполагать выполнение следующих условий: каждая пометка а е L пред- ставляет собой шкалу (а,, ..., ац), где k = |£|, а а, = 1 тогда и только тогда, когда 7-й элемент из £ принадлежит множеству, описанному пометкой «; П — операция ®; О = (0*); 1 = (!*); любая функция fmE имеет вид/(а) = (а Ф Ь) ® с, где b, с е L. А. Для любых b и с из L функция fla) = (а Ф Ь) ® с является дистрибутивной. Алгоритм 10.5. Простой итеративный алгоритм разметки Дано. Схема свойств л и некоторая нумерация F вершин уграфа бл. Требуется. Полная разметка А схемы л. Метод. проц ПРОСТОЙ ИТЕРАТИВНЫЙ АЛГОРИТМ = 1. А : разметка = {(р, 1): р р0} vj {(Ро, а0)}; 2. флаг = 1; 3. пока флаг цикл 4. флаг := 0; 5. для 7 от 1 до л через 1 цикл 6- P-F-'G); 7. а := ® {ЦА(нач(и})): и е ЗАХОД(р)} 8. если а * А(р) то А(р) := а; флаг := 1 все все все все Б. Алгоритм 10.5 корректен и требует не более О((1 + 2)/и) расширенных операций, где I — глубина нумерации F. В. Если л— сводимая схема, то алгоритм 10.5 требует O((d(G-n) + 2)ли) расширен- ных операций, где d(G-n) — длина последовательности сведения уграфа схемы. Можно усовершенствовать алгоритм 10.5: не выполнять операторы 6—8 для тех вершин, значение разметки на всех предшественниках которых не изменилось при предыдущей итерации. Алгоритм 10.6. Алгоритм разметки с рабочим списком Дано. Схема свойств л. Требуется. Полная разметка А схемы л.
800 Часть II. Применение графов и граф-моделей Метод. Реализуется процедурой С РАБОЧИМ СПИСКОМ; в ней АКТИВ — множе- ство всех тех вершин схемы, влияние которых на вид результирующей решетки еще не учтено. проц С РАБОЧИМ СПИСКОМ = 1. А : рвзметка = {(р, 1): р -г- р0} о {(ро, а0)}; 2. АКТИВ = Х; 3. пока АКТИВ # 0 цикл 4. q := э АКТИВ; 5. для всех р из ПРЕЕМ(д) цикл 6. а := ® [ЦА(нвч(и))): и е ЗАХОД(р)} 7. если а *А(р) то А(р) := а; АКТИВ <— р все все все все В алгоритмах 10.5 и 10.6 при каждой обработке вершины осуществляется проверка изменения ее пометки. Эта проверка может быть ликвидирована. Алгоритм 10.7. Алгоритм разметки с укладкой Дано. Схема свойств л и ее сильная укладка F. Требуется. Полная разметка А схемы л. Метод. Две процедуры С СИЛЬНОЙ УКЛАДКОЙ 1 и С СИЛЬНОЙ УКЛАДКОЙ 2, реализующие разные формы использования сильной укладки при решении задачи. Первая из них наглядно демонстрирует промежуточный характер данного алгоритма по отношению к алгоритмам 10.5 и 10.6 в смысле выполняемых ими избыточных пе- ревычислений А, а вторая позволяет легко оценить время работы алгоритма на схемах с ограниченным числом дуг, исходящих из одной вершины, как О(|Т]) расширенных операций. проц С СИЛЬНОЙ УКЛАДКОЙ 1 = 1. А: разметка = {(р, 1): р * р0} о {(ро. во)}; 2. для i от 1 до |F| через 1 цикл 3. A(F(i)) := ® {ЦА(иач(и))) : и е 3AXO£((F(/))} все все проц С СИЛЬНОЙ УКЛАДКОЙ 2 = 1. А : разметка = {(р, 1): р * ро} и {(ро, а0)}; 2. для i от 1 до |F| через 1 цикл 3. для всех и из ИСХОД((Е(/)) цикл 4. А(кон(и)) := А(кон(и)) ® {fu(A(F(i))) все все все
Глава 10. Потоковый анализ программ 801 10.5.5. Факторизация Факторизация это прием замены глобальной оптимизации серией квазилокаль- ных, базирующихся на представлении программы в виде иерархии фрагментов опре- деленного вида. Каждое применение квазилокальной оптимизации осуществляет не- зависимую обработку одного фрагмента иерархии, при которой фрагменты, непо- средственно вложенные в данный, выступают как элементарные операторы. Факторизация позволяет применять более сложные и мощные алгоритмы анализа и преобразований, поскольку сущесзвенно сокращается объем одновременно рассмат- риваемой информации о программе, а также использовать более эффективные спе- циализированные алгоритмы, ориентированные на определенную структуру фраг- мента (луч. интервал, гамак и т. п.). Пусть имеется схема свойств л = (G, L. F, М, а0), которая строится над полурешеткой свойств L = 2Л, где Е — некоторое конечное множество, а П — операция пересечения в нем, и множеством преобразователей пометок F, состоящим из функций Дх) = (.г ^Aj) п В/, где Aj, В/е L. Для любой дуги и схемы л через Mt(u) и Mi(u) будем обозначать соответственно элементы А^ и В, определяющие функцию Пусть Go, G|,..., G,.— некоторое /l-представление уграфа G схемы л. Для любой вер- шины р е X, / е [1 : г], через Ср обозначим альт уграфа G, _ ь который стягивается в вершину р при переходе к G,. Уграф С(р) — это альт Ср, к которому добавлена фик- тивная вершина в качестве начальной (начальная вершина альта Ср— единственный преемник фиктивной вершины); множеством конечных вершин уграфа С(р) объявля- ется множество выходных вершин альта Ср. Уграф С(р, и), где р е X,. ie [1 г], и е ИСХОД(р) — это подграф графа G,, образованный множеством вершин Ср и на- чальной вершиной альта CK„„(„j; начальной вершиной уграфа С(р, и) является началь- ная вершина альта Ср, а конечной — начальная вершина альта Ск„„ц,у Алгоритм 10.8. Факторизованный алгоритм анализа Дано. Схема свойств л = (G, L, F, М, ай) и ^-представление Go, Gb ..., G, ее уграфа G. Требуется. Такое расширение М на множество всех уграфов Go, Gb ..., Gr, что для любой дуги и из G,(z е [1 : г]) функция f„ = М{и) является функцией эффекта альта схемы G, соответствующего вершине иач(и), при переходе по дугам схемы G соот- ветствующим дуге w; полные разметки для всех схем л0, ль ..., лг, где л0 = л, а для лю- бого / е [1 : г] схема л, — это (G,, £, F, Мь а0), в которой /Ц — сужение М на G,. Метод. Выполнение алгоритма состоит из двух этапов. На первом этапе работает процедура СНИЗУ-ВВЕРХ, осуществляющая расширение М с использованием функ- ции РАЗМ1. Вызов РАЗМ1(л') вычисляет пометку конечной вершины схемы л' в ее полной разметке. Второй этап— это выполнение процедуры СВЕРХУ-ВНИЗ, ис- пользующей процедуру РАЗМ2. Вызов РАЗМ2(л', R), где л'= (G' = (X', U'), F’, L', М\ а'о), a R: Y -» L для некоторого Y о X', перевычисляет R таким образом, что /?(/?) по- лучает в качестве нового значения пометку вершины р в полной разметке схемы л', еслир е X'. и не изменяется, еслир~е X'. 26 Зак. 202
802 Часть II. Применение графов и граф-моделей проц СНИЗУ-ВВЕРХ = 1. Н = {(р, ty.p е Xi, / е [1 : г], t — число дуг, исходящих из вершин С(р)} 2. АКТИВ = X, 3. пока АКТИВ # 0 цикл 4. р:= э АКТИВ; 5. для всех и из ИСХОД(р) цикл 6. М,(и) = РАЗМ1(С(р, и), F, L, М, 0); 7. /И2(и) := РАЗМ1(С(р, и), F, L, М, 1); 8. если q — такая вершина, что р е C(q) то 9. H(q):=H(q)-1; 10. если (H(q) = 0) л(д ё Хг) то АКТИВ <— q все все все все все; проц СВЕРХУ-ВНИЗ = 1. К = Ми {(и, е): нач(и) — фиктивная вершина}; 2. R = {(р, 1): р е X;, / е [0 : г], р * G} vj {G, ао}; 3. АКТИВ =ХГ; 4. пока АКТИВ # 0 цикл 5. р := э АКТИВ; РАЗМ2((С(р), F, /, К, R(p)), R); 6. для всех q из С(р) - Хо цикл АКТИВ <- q все все все А. Алгоритм 10.8 корректно осуществляет расширение М на множество всех дуг уграфов Go, GbGr и вычисление полных разметок схем л0, ль л,. Заметим, что графб^ получается из графов Go, Gh ..., Gr путем склеивания их одина- ковых вершин, а также путем переключения дуг, заходящих извне в начальную вер- шину q альта Ср, с вершины q на вершину р и добавления фиктивной дуги (р, q) для каждого альта СР Таким образом, каждые вершина и дуга уграфов Go, Gb ..., Gr в графе Ga представлены в единственном экземпляре. Это позволяет реализовать фак- торизованный алгоритм анализа на Ga без оператора 7 процедуры СНИЗУ-ВВЕРХ. Еще заметим, что если до работы алгоритма факторизованного анализа сопоставить каждой фиктивной дуге графа G/ тождественную функцию е, то это позволит при выполнении процедуры СВЕРХУ-ВНИЗ не строить схему (С(р), F, L, М', R(p)), по- скольку она уже присутствует в Ga (р— это фиктивная начальная вершина у С(р) и ей уже приписана пометка R(pJ). Следует заметить, что алгоритмы процедуры РАЗМ2 и функции РАЗМ1 могут учиты- вать структуру альтов Ср. Например, если р представляет составной альт исходной схемы, то Ср— это луч, и в этом случае алгоритм нахождения полной разметки — это построение композиции функций. Если же ^-представление уграфа G является
Глава 10. Потоковый анализ программ 803 его интервальным представлением, то каждый альт Ср является интервалом, что по- зволяет в процедуре РАЗМ2 и в функции РАЗМ1 решать задачу нахождения полной разметки за две итерации. 10.5.6. Свойства схем анализа свойств состояний Уже отмечалось, что не все задачи потокового анализа могут быть решены точно и эффективно. Различные свойства схем, некоторые из которых упоминались в разд. 10.5.2, влияют на существование и точность решения, а также на те методы, которые можно применять для нахождения решения, и их свойства. Было предложено много таких свойств, существенно различающихся по определению, среди которых есть как разные термины для одних и тех же свойств, так и одинаковые термины, ко- торые используются для разных (часто лишь слегка различающихся, но иногда пол- ностью независимых) свойств. Более того, хотя проводились исследования многих из них, нет явного выделения направлений и приложений с описанием их влияния на сложность процедуры потокового анализа. Также не всегда по их описаниям не- посредственно видно, являются ли обсуждаемые свойства свойствами полурешетки или функционального пространства (или присваиванию, начальным значением или уграфу). Полурешетка Поскольку наиболее легко обрабатывать уграфы, в которых каждый путь конечен, наиболее простые полурешетки являются конечными. Конечные полурешетки замк- нуты относительно произвольных (не пустых) пересечений, но требования к беско- нечным полурешеткам предполагают лишь замкнутость относительно конечных пе- ресечений. Некоторая полурешетка L называется замкнутой, если она является замк- нутой относительно произвольных не пустых пересечений, включая бесконечные пересечения. Условия "локальной конечности" означают не только то, что L является замкнутой, но также то, что каждое бесконечное пересечение равно некоторому пересечению только конечного числа своих аргументов. Говорят, что полурешетка удовлетворяет условию обрыва убывающих цепей, если является конечной любая убывающая цепь в решетке v, > V2 > ... . Если L удовлетворяет условию обрыва убывающих цепей, то всякое пересечение л v элементов из L эквивалентно пересечению конечного под- veA множества А. Если помимо этого длины убывающих цепей, начинающихся с v, = b, ограничены некоторой функцией Ь, то говорят, что L имеет конечную высоту. Если она ограничена некоторой константой к, не зависящей от то говорят, что L имеет строго конечную высоту и имеет высоту к для заданного значения к. Полурешетка L с 1 имеет конечную высоту тогда и только тогда, когда L имеет строго конечную вы- соту. Однако множество натуральных чисел N (с отношением меньше или равно) об- разует полурешетку конечной высоты, которая не является решеткой строго конечной высоты. Любое множество w, большей мощности, например, определяемое уравнени- ем w + 1 = N гл {w} и имеющее множество континуум, является полурешеткой, обла-
804 Часть II. Применение графов и граф-моделей дающей свойством обрыва убывающих цепей, но не являющейся полурешеткой ко- нечной высоты. Наконец, говорят, что решетка L является полной относительно функционального пространства F, если каждый элемент из L представим в виде /(0) для некоторой функции f е F. Понятно, что для заданных G, F, М при определении решетки L можно ограничиться рассмотрением только тех ее элементов, которые достижимы от 0; можно также ограничиться рассмотрением £', состоящим из тех элементов, которые представимы в виде л{[Л/(Р,)](0) : / е А} для конечного множества индексов А и ко- нечного пути Р„ начинающегося в р„. Последняя полурешетка всегда является замк- нутой относительно конечных пересечений, но не обязана быть замкнутой относи- тельно бесконечных пересечений. В частности, некоторая бесконечная последова- тельность итераций функции может не иметь нижней границы. Пусть С является циклом, и рассмотрим, как обычно, множество путей, соответствующих нулю или большему числу проходов по С, {е, Л/(С), М(С || С), М(С || С || С), Пересечение этого бесконечного множества итерации не должно принадлежать £', даже если оно в L. Аналогично, F не обязано быть замкнутым, т. е. пересечение бесконечного множе- ства функций не обязано быть в F. Имеется определенная взаимосвязь между замы- канием и полнотой L, которые соответствуют взаимосвязи между дескриптивной мощностью и простотой представлений функций в F. Если L обладает свойством об- рыва убывающих цепей, то все пересечения конечны, и рассмотренные проблемы не возникают. Функциональное пространство Наиболее интересными представляются свойства F. Структура полурешетки L инду- цирует структуру полурешетки на F: П f< /. g тогда и только тогда, когда/(.v) <L g(x) для всех х е L; П h =f л g тогда и только тогда, когда h = max {j : j(x) — fix) л g(x),\/ x e L}. Таким образом, пересечение f и g в F всегда не превышает поэлементного пересече- ния /и g в L. Ранее приводимое определение и большинство применений требуют, чтобы пересечение в F совпадало с поэлементным пересечением. Более того, обычно предполагается, что F содержит тождественную функцию е и константную функцию 0, а также если имеется I е £, то и константную функцию 1. Однако аппроксимирующие полурешетки и функциональные пространства могут не иметь пересечений в F, равных поэлементным пересечениям. Если функциональное пространство F аппроксимируется меньшим пространством F', F' может быть замк- нутым относительно поэлементного пересечения. Но тогда, по крайней мере, воз- можно, что некоторые последовательности пересечений итераций функции/больше не являются выразимыми в F'. Имеется два основных класса свойств функциональных пространств. Большинство таких свойств Р определяется для индивидуальных функций /е F. Говорят, что F обладает свойством Р, если ему удовлетворяет каждая/е F. Алгебраические свойст-
Глава 10. Потоковый анализ программ 805 ва определяются в терминах свойств морфизма F как некоторого пространства функ- ций на L, рассматриваемом как упорядоченное множество, полурешетка или замкну- тая полурешетка. F также является замкнутым относительно композиции, и для него особенно важны пересечения последовательностей итераций функций, поскольку если/= ЛУ(С) для некоторого цикла С, то /у/' представляет ”Л/(С*)". Свойства пере- до сечений итераций делятся на свойства локальной конечности и свойства замыкания. Свойства локальной конечности разрешают усечение — замену бесконечного пересе- чения функциональных итераций на некоторый ее начальный конечный сегмент. Свойства замыкания позволяют извлекать суммарную информацию с помощью точ- ной или аппроксимирующей функции даже тогда, когда пересечение итераций не обязательно усекается. Алгебраические свойства Некоторая функция f называется монотонной, если она является на L морфизмом упорядоченного множества, т. е. если V/е F Vx, у е L : х <у ->/(х) < f(y\ и антимо- нотонной, если V/е F Vx, yeL:x<y—> f(x)>f(y). Монотонность эквивалентна следующему свойству V/ е F \fx,y е L -f(x л у) < f(x) л f(y). Функция f называется дистрибутивной, если V/е F Vx, у е L : f(x л у) =/(х) л f(y), и непрерывной, если f является морфизмом замкнутых полурешеток, т. е. L является замкнутым относительно произвольных (непустых) пересечений для любого f е F и любого не пустого {х,} ,е/ с L выполняется равенство /(лх,) = л /(х,). /е/ /е/ Таким образом, монотонные функции перерабатывают цепи из области определения в цепи образов, дистрибутивные функции переводят конечные пересечения в пересе- чения образов, непрерывные функции сопоставляют произвольным пересечениям пересечения образов. Если L является решеткой, то можно также определять антиди- стрибутивные и антинепрерывные функции, которые переводят пересечения в объ- единения образов. Каждая непрерывная функция является дистрибутивной и всякая дистрибутивная функция является монотонной, но не всегда верно обратное. Однако если F или L является конечным, то дистрибутивность означает непрерывность, и если L является цепью, то монотонность означает дистрибутивность. Если каждая f е F является монотонной (дистрибутивной, непрерывной), то таким является функциональное пространство F и задача анализа свойств. Задачи анализа свойств с классами немонотонных функций обычно не рассматриваются. Свойства локальной конечности Указанные свойства L означают поэлементную конечность для некоторой функции/ из F, но не какого-то унифицированного свойства в общем. Если L обладает свойст- вом обрыва убывающих цепей, то для каждых f^F и хе£ последовательность к л /'(х) стабилизируется на некоторой итерации л(х), но не требуется, чтобы мно-
806 Часть II. Применение графов и граф-моделей к жество п(х) было бы ограничено для тех случаев, когда л /' (х) не стабилизируется. Таким образом, не требуется, чтобы F обладала свойством обрыва убывающих цепей. Наоборот, даже если L не обладает свойством обрыва убывающих цепей, F может быть достаточно ограниченным, чтобы цепи итераций вели себя хорошо. Для функ- к I ций/изТ- определяются функции / '= л/'(х). Говорят, что F является ограниченным, если для любой f е F цепь {/w} является ко- нечной, к-ограниченным, если длина такой цепи не превышает к (независимо от/), и к-полуограниченной, для отдельных функций, если для всех х,ye L и г > к имеем /г(х) >/w(x) л fk(y). Понятие ^-ограниченности здесь определено для функций в об- щем случае; для монотонных функций оно эквивалентно условию/* >/,А|. ^-ограниченность означает ^-полуограниченность, которая в свою очередь означает (к + ^-ограниченность. F называется однородно ограниченной, если оно ^-ограничено для некоторого к. Полуограниченность (исключая 1-полуограниченность) не доказала своей важности в решении "неограниченных" проблем, но, как было показано Тарья- ном, естественным образом возникает в проблемах квалифицированных путей. Если L имеет высоту к, то F является Л-ограниченным, но обратное не всегда имеет место. В частности, если L является решеткой произведения L=L\ х £2 х — х Lp, и F — про- изведением функций на компонентах F = Ft х F2 х ... х Fp, тогда длина цепей ограничена эффективной высотой L = тах{высота £,}. Если £, и F, являются повтор- ными вхождениями одного и того же множителя с высотой г, то £ будет иметь высоту гр, a F будет иметь высоту, равную высоте £(, равную г, равную эффективной вы- соте £. Быстрота и скорость, 2-ограниченность и 1-полуограниченность исторически играют важную роль в потоковом анализе, f называется быстрой, если она является 2-ограниченной, т. е. для монотонной функции это свойство равносильно f °f>f ле. Быстрота очевидно связана с идемпотентностью f ° f=f или слабой идемпотент- ностью f °/>f Идемпотентность является свойством функций в каждой из четырех классических внутрипроцедурных проблем потокового анализа: достигающие опре- деления, живые использования, доступные и сильно занятые выражения. Быстрота позволяет обрабатывать цикл в алгоритмах элиминации. f называется быстрой по Кэму— Ульману, если она является 1-полуограниченной, т. е. для монотонной функции это эквивалентно свойству Vx, у е £ : /(х) >у л х л/(х). Исходное определение Кэма и Ульмана требовало выполнения условия V/ g 6 е F Vx е £ :/g(0) > g(0) л/[11(х). Данные два определения эквивалентны для полных решеток. Если £ имеет I и F является монотонным, быстрота эквивалентна свойству Ууе£:/(у)>улА1). ^-ограниченность означает, что все влияния на значение стационарной разметки про- являются до к-й итерации, а ^-полуограниченность, что вклад этой к-й итерации явля- ется константным. Таким образом, быстрота означает, что один проход по некоторо-
Глава 10. Потоковый анализ программ 807 му циклу будет суммировать весь его вклад, а скорость, что вклад этого цикла не за- висит от значения на начальной вершине цикла. Свойства замыкания Даже если цепь {/[А|} является бесконечной, может существовать вычислимое пере- сечение или некоторое хорошее нижнее приближение к пересечению. Более того, даже если данная цепь конечна, может существовать более быстрый метод вычисле- ния пересечения или, по крайней мере, некоторой его аппроксимации Быстрые замыкания Для f е F функция /ас является монотонной, убывающей и меньшей, чем /; можно использовать пересечения ее итераций в качестве оценок пересечений итераций f Определим /<<! = (f /\ е){* lf. Если F является монотонным, то/*'*</|,], и если F дист- рибутивно, то они равны. Грэхам и Вегман определяют быстрое замыкание fcw функции f как наименьший элемент в убывающей цепи {/'*}. Функция fcw являет- ся идемпонентной и поэтому быстрой. Если F однородно ограничено числом к, то/gw существует (с небольшим значением к), но fcw может существовать, даже если {/*'} является бесконечной. Другое определение, приведенное Розеном, по существу имеет следующий вид: fK является первым элементом/<г), который меньше всех элементов последовательности {/’,‘1}, т. e.fk>для всех к > г. Опять, если F монотонно, то достаточно, что fr = /*'*. Не гарантируется, что функция fR является быстрой, но она существует, если fcw существует, причем наименьший "порядок" г для ft не превышает его для fcw. Когда f является дистрибутивной, fK и7gW равны. Поэтому многие результаты применимы для обоих быстрых замыканий. Если/является монотонной, то/а е (и, следовательно, быстрое замыкание) имеет ту же самую неподвижную точку, что и / Однако быстрое замыкание не является ото- бражением функциональных пространств, оно не дистрибутивно относительно пере- сечения или композиции. Хотя (f ° g) л е = (/а е) ° (g л е), в общем случае не является истинным ни одно из следующих свойств: □ (/a g) а е = (/л е) л (g а е); o/°g)‘=/4; П быстрое замыкание функции/° g равно fcw ° gGW; □ замыкание функции/л g равно fcw a gGw- Таким образом, эквивалентность неподвижных точек означает меньше, чем кажется на первый взгляд, поскольку последовательные или кратные циклы могут не обраба- тываться точно. Также имеются задачи потокового анализа, для которых F не имеет быстрого замыкания; Купером приводится дистрибутивная (фактически непрерыв- ная) схема для нахождения синонимов, в которой в общем случае нет быстрых замы- каний.
808 Часть II. Применение графов и граф-моделей Бесконечные пределы Пусть (по аналогии с регулярными выражениями) определена функция /* = СО СО г 1 = {/}=/\ {/“}, если она существует. Если полурешетка не является замкнутой |=о i=O или F не является непрерывным, функция f* не обязана существовать в F. По сущест- ву,/* является (рефлексивным) транзитивным замыканием функции / Можно также определить расширение быстрого замыкания f :=/\ {/'’}. Поскольку/1'1 и/1'1 обра- /=о зуют убывающие цепи, функции/* и/.- фактически являются пределами последова- тельностей итераций, когда они существуют. Если /’ существует для всех /е F, то также существует fn = (fл е)‘, но обратное не всегда верно. Если /* =/1'1, то /* может быть вычислено за О(г) пересечений и композиций. Если/;=/о\у=/<г|, то fcw может быть вычислена за O(log_2r) операций. Аппроксимации Более меньшая аппроксимация /® к/* называется псевдотранзигнивны.м замыканием функции/ если справедливы следующие два свойства: □ /®(х) </'(х) для всех х из L и / > 0; П если х е L и х </(х), то х </®(х). Функция /jW, а также функция /* удовлетворяют этому определению, если они есть в F. Фактически/‘ является максимальной из таких функций. Замыкания и аппроксимирующие решетки Быстрые замыкания и псевдотранзитивные замыкания дают способы замены исход- ной задачи потокового анализа л на другую задачу л', которая во многих случаях ока- зывается менее точной, но более предпочтительной с точки зрения временной слож- ности нахождения решения. В общем случае L и F остаются неизменными, но М(и G) могут изменяться, что связано с рассмотрением замыканий в качестве операций эли- минации. Для М решение могло быть не вычислимым за конечное время, но гаранти- руется, что М' является разрешимым. Некоторая функция/называется скорой по Розену с параметром если существует псевдотранзитивное замыкание/ вычислимое не более чем за операций (пересече- ний и композиций). Говорят, что F и л имеют транзитивное (/”) замыкание или псев- дотранзитивное (f®) замыкание, если это свойство справедливо для всех / е F. F и л называются скорыми по Розену, если каждая /в F является скорой по Розену для не- которого параметра t@. Задачи потокового анализа с быстрым замыканием дают при- меры скорых по Розену схем. Если схема является Л-ограниченной, то /jW =/1*1 и = O(log2 Л). Если/является дистрибутивной, To/iu согласуется с/. Если/является быстрой, то/;W =/л е и = 1. П. Кузо и Р. Кузо предлагают альтернативный подход. Эффект от циклического пото- ка в некотором интервале суммируется и аппроксимируется путем замены функций
Глава 10. Потоковый анализ программ 809 потока по некоторым из его дуг (функций эффектов дуг) на функции расширенного потока. Оператор расширения V является бинарным оператором, аналогичным спи- рали Розена @, который гарантирует замену произвольных убывающих цепей пере- сечений на пересечение конечных цепей. По крайней мере, по одной дуге каждого цикла должна быть выполнена операция расширения Поскольку любой достаточно длинный путь в интервале должен содержать некоторый простой цикл более, чем не- которое заданное число раз, последовательность пересечений значений, наблюдае- мых в этой точке, должна стабилизироваться и, таким образом, в конечном счете дать поток внутри интервала. Другие свойства схем Ряд используемых свойств схем относится к представимости или локальности реше- ния. Говорят, что задача потокового анализа является битвекторной, если L может быть естественным образом вложена в некоторую решетку множества подмножеств (например, множество подмножеств определений для достигающих определений), так что каждая / в F работает отдельно на каждом элементе базового множества Ре- шетки битвекторных проблем могут быть представлены в виде решеток на битовых строках (шкалах) и функций в виде стандартных логических операций. Четыре клас- сические проблемы обычно представляются в виде битвекторных проблем. Некоторая задача называется разложимой, если L является решеткой произведения и F действует на L, производя линейное пересечение на каждом отдельном множителе (т. е на любом заданном множителе каждая функция является либо константой, либо пересечением с константой). В разложимой проблеме графы могут конструироваться для каждой проблемы, образующей сомножитель, в которой неподвижная точка мо- жет быть вычислена в рамках некоторого единственного топологического порядка обхода графа (однако конструирование графа может представлять сложность, а число проблем, выступающих в качестве сомножителя, может быть достаточно большим). Термины потоково-чувствительный и потоково-нечувствительный часто исполь- зуются для разделения задач потокового анализа на две группы. Содержательно по- токово-чувствительные— это те задачи, которые для вычисления результатов в большей степени учитывают пути распространения информации. Это различие для межпроцедурных задач приводит к разделению их на те, которые учитывают внутри- процедурные эффекты, и те, которые не делают этого. Однако пока нет единства в понимании указанных термов для всего класса задач и большинство определений, встречающихся в литературе, относится только к определенным подклассам задач потокового анализа. Внутрипроцедурные и межпроцедурные задачи Большинство задач потокового анализа может рассматриваться как теоретико- множественные задачи, связанные с решением системы линейных уравнений на мно- жествах, или как задачи замыкания где решение имеет вид подходящего замыкания некоторого отношения. Классические проблемы и многие другие внутрипроцедурные задачи являются теоретико-множественными, в то время как стандартные межпроце- дурные задачи, включая множество границ и нахождение синонимов, являются по
810 Часть II. Применение графов и граф-моделей существу задачами замыкания. Вместе с тем, имеются внутрипроцедурные проблемы замыкания и межпроцедурные теоретико-множественные проблемы. В общем случае, межпроцедурные проблемы более трудны, чем внутрипроцедурные, и проблемы за- мыкания более сложны, чем теоретико-множественные проблемы. Межпроцедурные проблемы не только должны суммировать внутрипроцедурную информацию. Их гра- фы потока управления могут иметь краткие дуги, соответствующие кратным вызовам к одной и той же процедуре, и многократные выходные (но единственную входную) вершины, соответствующие разным местам вызова внутри вызывающей процедуры. Нетривиальные зацикливания также достаточно распространены. Проблема замыка- ния имеет больше сложностей при циклах и обычно требует поддержки большей ин- формации. Проблема, которую не легко выразить в виде либо теоретико-множественной про- блемы, либо проблемы замыкания, такая как протягивание констант, имеет тенден- цию быть еще более сложной. Более того, межпроцедурная форма любой задачи по- токового анализа является обычно более сложной для решения, чем внутрипроцедур- ная версия той же самой задачи. Схема свойств известных проблем Достижимость (множество вершин уграфа достижимых на путях от р0) и ее обраще- ние являются проблемами связности графа, определимых в терминах только управ- ляющего графа (независимо от ассоциированного кода); они являются дистрибутив- ными и быстрыми. Четыре классические проблемы зависят от кода, но также являют- ся дистрибутивными и быстрыми. Полурешетка в каждом случае является прямым произведением множеств подмножеств, и функции — это функции над множествами, определенные с использованием объединения и пересечения. Рефлексивное транзи- тивное замыкание является близко связанной с задачей достижимости, но не является задачей объединений-пересечений. Прямая проблема транзитивного замыкания при- писывает вершине v множество всех дуг транзитивного замыкания, начинающихся в v Она является дистрибутивной и скорой, но не быстрой. Некоторая комбинация прямой и обратной задач, за которой идет одна итерация "на месте", могла бы тогда охватить в v множество дуг, получивших из путей, проходящих через v. Задача излишних переменных является задачей с множественными значениями. Оп- ределение "d= (переменная х, программная точка р)" называется излишним, если оно нигде не используется или используется только в излишних определениях. Эта про- блема является дистрибутивной, но не скорой. В любой конкретной постановке она является ^-ограниченной, где к зависит от цикловой структуры и длины цепочек оп- ределений. Задача о частично избыточных выражениях является другой задачей с множественными значениями, которая очевидно является не скорой и, возможно, не дистрибутивной. Задача о протягивании констант является монотонной, но не дистрибутивной, и являет- ся скорой. Вычисление регулярных выражений можно сформулировать в виде схемы анализа свойств. Она является дистрибутивной, но не ограниченной, поскольку она требует
Глава 10. Потоковый анализ программ 811 замыкания (Клини). Покрытие потока или задача вычисления выражений путей для некоторого заданного уграфа G по существу эквивалентна задаче нахождения для множеств путей между каждой парой вершин регулярных выражений, которые опре- деляют эти пути по уграфу. Межпроцедурная задача о множестве связываний также является дистрибутивной. В некоторой заданной конкретной постановке она является ^-ограниченной, где к зависит от максимальной длины простой цепочки вызовов и от порядков перестано- вок формальных параметров, индуцированных циклической последовательностью вызовов. Синонимия относится к категории задач множества связываний Задачи о возможно изменяемых и об обязательно сохраняемых являются вариациями задачи о достижимости; их сложность, по крайней мере, не меньше сложности задачи о множестве связываний. Задача об обязательно определенных (обязательных резуль- татах), с другой стороны, является (в исходном определении Баннинга) контекстно- чувствительной и монотонной, но не дистрибутивной. Задача об обязательно опреде- ленных неявно использует информацию о множестве связываний и поэтому должна быть не меньшей сложности. Вывод типов и синонимия через указатели определяются на полурешетках неограни- ченной высоты, но решаются на аппроксимирующих решетках конечной высоты; вывод типов является также не дистрибутивной задачей. Проблема программных ут- верждений (или проблема инвариантов циклов) не может быть ни ограниченной, ни дистрибутивной, поскольку она предполагает решение всех задач анализа свойств (на монотонных схемах), но является монотонной, поскольку более сильна, чем преду- словие оператора, и более сильна, чем постусловие. Условное протягивание констант и инкрементально избыточные выражения могут быть представлены как задачи выражений квалифицированных путей, но не просто выражаются в виде задач на очевидной схеме. Задача инкрементально избыточных выражений является «-ограниченной, где п является параметром определения. Проблемы анализа свойств априорно не ограничены некоторым фиксированным к и могут иметь постановки с произвольно большой сложности. Показано, что задача о возможных изменениях является TVP-полной, а межпроцедурная задача доступных выражений является со-ТУР-полной в случае синонимии, даже без указателей рекур- сии. Было показано, что решение задачи процедурных параметров, т. е. фактических процедур, сопоставленных процедурным переменным при некоторой цепочке вызо- вов, является Л'Р-БРАСЕ-трудной даже без синонимии, вложенности процедур или "значимого управляющего графа". Свойства конечности и замыкания Поскольку/* и fK являются обоснованными псевдотранзитивными замыканиями,/® существует для некоторой заданной /g F, если существует каждая из них. Когда за- мыкания /* существуют для всех/е F, тогда также будут существовать расширенные быстрые замыкания поскольку они являются замыканиями /ле. Из определения скорости по Розену следует, что/® существует.
812 Часть II. Применение графов и граф-моделей Ограниченность означает, что f* существует, а также существование быстрых замы- каний. Существование быстрого замыкания f означает, что существует . Быстрое замыкание по Грэхам—Вегману заключает в себе быстрое замыкание по Розену, ко- торое в свою очередь включает в себя скорость по Розену для данной f Строго конечная высота в L означает однородную ограниченность, поскольку цепи функциональных значений не могут превышать по длине произвольные цепи в L (фактически высота к в L означает ^-ограниченность в F). Как уже отмечалось, (А-^-ограниченность означает (Л-1)-полуограниченность, из которой следует A-ограниченность, которая в свою очередь означает ограниченность; быстрота явля- ется 2-ограниченностью, скорость является 1-полуограниченностью, а идемпотент- ность означает быстроту. Таким образом, только свойствами конечности и замыкания, которые могут не зави- сеть от существования псевдотранзитивного замыкания, являются свойства обрыва убывающих цепей или конечность высоты в L. Однако, если основанная на значениях итерация используется для решения некоторой схемы, в которой решетка обладает свойством обрыва убывающих цепей (и уграф является конечным), она за конечное число шагов достигает стационарной разметки, даже если оператор псевдотранзитив- ного замыкания может не существовать для всего F. Пусть одновременная итерация применима для безопасного начального предположения Хо. По индукции для задан- ной вершины v последовательность значений %„(г), видимых в заданной вершине v, будет не возрастающей. Далее, до тех пор пока стационарное решение не будет дос- тигнуто, некоторые компоненты X будут изменяться при каждой итерации. Но при этом значение в точке v может убывать только конечное число раз. Известны примеры, показывающие отсутствие общих отношений между алгебраиче- скими свойствами и свойствами конечности и замыкания. Фактически, хотя немоно- тонные функции редко представляют интерес, скорость, являющаяся наиболее силь- ным из свойств конечности, не гарантирует монотонности, являющееся слабейшим из алгебраических свойств. Для любой пары свойств из декартового произведения {ско- рая, быстрая, другая} х{дистрибутивная, монотонная, другая} найдется небольшая схема анализа свойств, которая обладает указанной парой свойств. Наконец, следует заметить, что к — 1 и к-ограниченность различаются в каждом из случаев, связанных с алгебраической классификацией. Библиографический комментарий Задачам потокового анализа посвящена обширная библиография, привести которую здесь не представляется возможным. Ссылки на наиболее важные работы по этим вопросам читатель найдет в работах [1—5, 12, 14, 17, 23, 48, 65] и обзорах [7, 16. 18, 59. 71]. Понятие уграфа как модели программы, описывающей структуру ее управляющих связей, впервые рассматривалось в работах [24, 25]. Там же были введены понятия закрытою и замк- нутого подграфов {закрытый подграф — это альт, а замкнутый — фрагмент с одной началь- ной и одной выходной вершинами), а также построены эффективные алгоритмы их выделения. Понятия начальных, конечных, входных и выходных вершин фрагмента были введены в рабо- тах [10, 11, 20], а граничных, стартовых и финишных— в [82]. Идея рассмотрения линейных
Глава 10. Потоковый анализ программ 813 участков была выдвинута в работе [26], гамаков и линейных компонент— в [9. 27|, простых и составных гамаков— в [12]. фактор-уграфов— в [14], гамачного представления и Л-графа — в [12]. Понятие /-области и А/-, Л'-, Т-, К- и /.-нумераций были предложены в работах [10, 13, 15]; там же были приведены эффективные алгоритмы их построения. Поиск в глубину и пря- мая нумерация вершин уграфа рассматривались в работах [44. 80], а вопросы анализа структур программ в глобальной оптимизации— в работе [54] Лоури и Медлок [57] описали алгоритм нахождения доминаторов за О(и4). В дальнейшем эта оценка была улучшена в алгоритмах Ахо и Ульмана [ 11, Пардома и Мура [66] и Тарьяна [81]. Ленгауэр и Тарьян в [56] описали рассмотренный нами почти линейный алгоритм и продемон- стрировали его преимущества по отношению к существующим алгоритмам на классе уграфов, встречающихся на практике. Небольшая нелинейность алгоритма была связана с реализацией набора — структуры данных для работы с пеисресекающимися множествами [75 76]. Харелом был предложен линейный алгоритм, но в его описании (46] были выявлены некоторые неточ- ности, которые, правда, в дальнейшем были сняты. В работе [33] был предложен новый, более простой линейный алгоритм нахождения доминаторов. который мы и включили в паше изло- жение. Проблемы ипкремсигалы101 о построения доминаторного дерева рассмотрены в работах [37. 73] Алгоритм нахождения отношения доминирования для сводимых уграфов взят из [12] Разработка метрик и мер, способных ранжировать программы по тому или иному критерию качества, а также создание инструментов, обеспечивающих их вычисление, являет ся одной из важных проблем метрологии качества программ. За справками мы отсылаем к обзорам [6, 28, 29, 84]. Мера Мак-Кейба была введена в работах [61, 62]; функциональное отношение — в работе [47], мера Пивоварского— в [63], тест ирующая мера— в [64]. мера на основе регу- лярных выражений— в [58]. характеристический многочлен в работах [36, 74]. Описанный в разд 10.4 алгорит м декомпозиции принадлежит Ружичкс [70]. Метод размет ки, впервые примененный Килделлом [55] для анализа свойств программ в целях их оптимизации, находит свое применение как в общей теории схем программ [8, 22]. так и при решении задач оптимизирующей трансляции [1. 16, 17. 30], параллельного программиро- вания [72], верификации |32], отладки [21, 53]. тестирования [67]. распараллеливания [35], векторизации |31 ] и конструирования программ [83] Как отдельное направление в системном и теоретическом программировании, анализ потока данных начал формироваться в работах Кэма и Ульмана [51, 52], Грэхама и Вегмапа [45] и Розена [68, 69], в которых на базе идей Килделла [55] была сформулирована общая постановка задачи потокового анализа свойств и предложены алгоритмы ее решения. Дальнейшее про- движение в этом перспективном и активно развиваемом направлении связано с работами [34, 38—43, 49. 60, 77 -79, 85]. Предпринимались успешные попытки учета в свойствах состояний априорно известной информации [19], а также нс всех путей по схеме (поскольку нс все из них выполнимы), а только так называемых разрешенных путей [50] Здесь, как и для схем Марты- нюка [25], удается от любой схемы, в которой специальными, внешними по отношению к то- пологии схемы средствами описаны ограничения на разрешенные пути, перейти к такой экви- валентной ей схеме, в которой все пути разрешены. Вместе с тем. при развитии потокового анализа были выявлены некоторые проблемы, относя- щиеся, главным образом, к исследованиям связи рассматриваемых свойств с реальным поведе- нием программы, ее стандартной семантикой. Некоторое решение этих проблем было предло- жено в подходе, получившем название абстрактной интерпретации [40—42, 60]. По мнению разработчиков этого направления потоковый анализ является лишь частью абстрактной интер- претации и ему недостает некоторых существенных деталей. Введением в проблематику анализа потока данных могут служить книги [48, 65] и обзоры [7, 16, 59, 71].
814 Часть II. Применение графов и граф-моделей Список литературы 1. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции.— М.: Мир, 1978.—Т. 2. 2. Евстигнеев В. А. Применение теории графов в программировании. — М.: Наука, 1985. 3. Евстигнеев В. А. Теория графов и программирование. — Новосибирск: Изд-во Новосиб. ун-та, 1978. 4. Евстигнеев В. А., Касьянов В. Н. Теория графов. Алгоритмы обработки деревьев. — Но- восибирск: Наука, 1994. 5. Евстигнеев В. А., Касьянов В. Н. Сводимые графы и граф-модели в программировании. Новосибирск: ИДМИ, 1999. 6. Евстигнеев В. А., Кожевникова Г. П. Топологические меры сложности программ. — М., 1989. — 30 с. — (Препр./АН СССР. ИТМ и ВТ. Новосиб. филиал. № 23). 7. Емельянов П. Г. Абстрактная интерпретация императивных программ // Системная ин- форматика. — Новосибирск: Наука. 1998. — С. 7—47. 8. Ершов А. П. Введение в теоретическое программирование. — М.: Наука, 1977. 9. Ершов А. П. Универсальный программирующий процессор И Проблемы прикл. математи- ки и механики. — М., 1971. — С. 103—116. 10. Касьянов В. Н. Анализ структур программ И Кибернетика. — 1980. — № 1. — С. 48—61. 11. Касьянов В. Н. Анализ управляющих графов программ И Системное программирова- ние.— Новосибирск. 1973. — Ч. I. — С. 133—154. 12. Касьянов В. Н. Введение в теорию оптимизации программ. Оптимизирующие преобразо- вания программ и их обоснование. — Новосибирск: ВЦ СО АН СССР, 1985. 13. Касьянов В. Н. Выделение гамаков в ориентированном графе// Докл. АН СССР.— 1975.—Т. 221, №5, —С. 1020—1022. 14. Касьянов В. Н. Методы анализа программ. — Новосибирск: Изд-во Новосиб. ун-та. 1982. 15. Касьянов В. Н. Об одном алгоритме выделения бикомпонент в ориентированном графе И Системное и теоретическое программирование. — 1974. — С. 235—243. 16. Касьянов В. Н. Оптимизация программ// Прикладная информатика.— М.: Финансы и статистика, 1983. — Вып. 2. — С. 38—75. 17. Касьянов В. Н. Оптимизирующие преобразования программ. — М.: Наука, 1988. 18. Касьянов В. Н. Теоретико-графовые задачи анализа управляющих графов транслируемых программ И Исследования по прикладной теории графов. — Новосибирск: Наука. Сиб. отд-ние. 1986. — С. 9—26. 19. Касьянов В. Н. Учет априорной информации при анализе свойств состояний программ// Математическая теория программирования. — Новосибирск. 1985. — С. 150—158. 20. Касьянов В. Н. Экономное преобразование несводимых графов И Системное и теоретиче- ское программирование.— Новосибирск, 1973. — С. 143—172. 21. Касьянов В. Н., Мирзуитова И. Л. Slicing: срезы программ и их применение.— Новоси- бирск, 2002. 22. Кривой С. Л. Об одном алгоритме поиска инвариантных соотношений в программах И Кибернетика. — 1981.— Т. 1. — С. 12—18.
Глава 10. Потоковый анализ программ 815 23. Липаев В. В. Тестирование программ. — М.: Радио и связь, 1986. 24. Мартынюк В. В. Выделение цепей в схемах алгоритмов // Жури, вычисл. математики и мат. физики —1961.—Т. 1,№ 1. — С. 151—162. 25. Мартынюк В. В. Об анализе графа переходов для операторной схемы// Там же.— 1965. — Т. 5, № 2. — С. 298—310. 26. Поддерюгип В. Д. Программа контроля для "Стрелы-3" (луч). - М.: ВЦ АН СССР, 1960 27. Поттосин И. В. О линеаризации программы и частичном ее упорядочении // Системное и теоретическое программирование. — Новосибирск, 1972. —С. 278—286. 28. Черноножкин С. К. Меры сложное™ программ (Обзор). — Новосибирск, 1994. — 36 с. — (Препр./ РАН Сиб. отд ИСИ. № 21) 29. Черноножкин С. К. Меры сложности программ // Системная информатика. — Новоси- бирск: Наука, 1997.— Выл. 5. Архитектурные, формальные и программные модели.— С 188—227. 30. Aho А. V., Sethi R., Ullman, J. D. Compilers: principles, techniques, and tools. Reading, — MA: Addison-Wesley 1986. 31. Allen R., Kennedy K. Automatic translation of FORTRAN programs to vector form // ACM Transactions on Programming Languages and Systems. — 1987. —Vol. 9. — P 491—542 32. Apt K. R. A static analysis of CSP programs// Leet. Notes Comput. Sci.— 1983.— Vol. 164.— P. 1—17. 33. Buchsbaum A. L., Kaplan H., Rogers A,, Westbook J. R. A new, simpler linear-time dominators algorithm // ACM Transactions on Programming Languages and Systems. — 1998. — Vol. 20. N6. —P. 1265—1296. 34. Burke M. An interval analysis approach toward exhaustive and incremental interprocedural data now analysis // ACM Trans. Program. Lang. Syst. — 1990. — Vol. 12. — P. 341—395. 35. Burke M., Cytron R. Interprocedural dependence analysis and parallelization // SIGPLAN No- tices — 1986 -Vol. 21, N 6, —P. 162 175. 36. Cantone G.. Cimitile A., Sansone L. Complexity in program schemes: the characteristic polino- mial // SIGPLAN Notices. — 1983. — Vol. 18, N 3. — P. 22—31. 37. Carroll M., Ryder B. G Incremental data flow update via attribute and dominator updates // ACM SIGPLAN-SIGACT Symposium on the Principles of Programming Languages. — ACM, New York, 1988. — 274—284. 38. Cocke .1. Global common subexpression elimination// SIGPLAN Notices.-— 1970.— Vol. 5. N 7. — P. 20—24. 39. Cooper, K. Analyzing aliases of reference formal parameters // Conference Record of the Elev- enth Annual ACM Symposium on Principles of Programming Languages. — 1984. — P. 281 — 290. 40. Cousot P., Cousot R. Automatic synthesis of optimal invariant assertions: Mathematical founda- tions//SIGPLAN Notices. — 1977. — Vol. 12, N 8 — P. 1—12. 41 Cousot P., Cousot R. Systematic design of program analysis frameworks// SIGPLAN No- tices.—1979.—Vol. 14, N L — P. 269—282. 42. Cousot P., Cousot R. Abstract interpretation frameworks П J. of Logic and Computation. — 1992. — Vol. 2, N 4. — P. 511—547.
816 Часть II. Применение графов и граф-моделей 43. Dijkstra Е. W., Gasteren A. A simple fixpoint argument without the restriction to continuity// Acta Informatica. — 1986. — Vol. 23. — P. I—8. 44. Earnest С. P.. Balke K. G., Anderson J. Analysis of graphs by ordering of nodes // J. ACM. - 1972.— Vol. 19,N 1, —P. 23—42. 45 Graham, S.. Wegman, M. A fast and usually linear algorithm for global data flow analysis // J. ACM.—1976 — Vol. 23.— P. 172—202. 46. Harel D. A linear time algorithm for finding dominators in flow graphs and related problems // Proceedings of the 17th ACM Symposium on Theory of Computing. —ACM, New York, 1985. P. 185—94. 47. Harrison W, Magel К. I. A complexity measure based on nesting level // SIGPLAN Notices. — 1981,- Vol. 16, N3.— P. 63—74. 48. Hecht M. S. Flow analysis of computer programs. — New York: Elsevier North-1 lolland. 1977. 49. Hecht M. S., Ullman J. D. A simple algorithm for global data flow analysis problems // SIAM .1. Comput.—1975. —Vol. 4, N 4. — P. 519—532. 50. Holley I., Rosen B. Qualified data flow problems// IEEE Trans. Software Eng.— 1981. Vol. 7. — P. 60—78. 51. Kam J. B„ Ullman J. D. Global data flow analysis and iterative algorithms// J. ACM.- 1976, —Vol. 23, —P. 158—171. 52 Kam .1. B., Ullman J. D. Monotone data flow analysis frameworks // Acta Informatica. 1077. —Vol. 7, —P. 305—317. 53. Kasyanov V. N. Some properties of fully reducible graphs // Inf. Proc. Lett. — 1973. — Vol. 2, N4.-P. 113—117. 54. Kasyanov V N., Trahtenbrot M. B. Program structure analysis in global optimization // Lecture Notes in Computer Science. — 1977. — Vol. 47. — P. 90—104. 55. Kildall G. A unified approach to global program optimization // Conference Record of the ACM Symposium on Principles of Programming Languages. — 1973. — P. 194—206. 56. Lengauer T., Tarjan R. E. A fast algorithm for finding dominators in a flow graphs // ACM Trans. Prog. Lang. Syst. — 1979. — Vol. 1,N L —P. 121—141. 57. Lowry E., Medlock С. M. Object code optimization// Comm. ACM.— 1969. — Vol 12. N L — P. 13—22. 58. Magel K. Regular expressions in a program complexity metrics // SIGPLAN Notices. — 1981. —Vol. 16, N 7. — P. 61—65. 59. Marlowe T. J., Ryder B. G. Properties of data flow frameworks. A unified model. // Acta Infor- matica. — 1990. — Vol. 28, N L — P. 121—163. 60. Marriot K. Frameworks for abstract interpretation// Acta Informatica.— 1993.— Vol. 30, N 2, —P. 103—129. 61 McCabe T. J A complexity measure// 2nd Intern. Conf on Software Eng.—- San Francisco, 1976, —P. 69—78. 62. McCabe T. .1. A complexity measure// IEEE Trans. Software Eng. — 1976. — Vol. 2, N 4. — P. 308—320. 63. Piwowarski P. A nesting level complexity measure// SIGPLAN Notices.— 1982.— Vol 17, N 9. — P. 44—60.
Глава 10 Потоковый анализ программ 817 64. Prather R. Е. An axiomatic theory on software complexity measure// Computer J. — 1984. - Vol. 27, N 4. — P. 340—347 65. Program Flow Analysis: Theory and Applications. — Englewood Cliffs, N.I: Prentice Hall 1981. 66. Purdom P. W., Moore E. F. Algorithm 430: Immediate predominators in a directed graph // Comm. ACM. - 1972. — Vol 15, N 8 - P. 777 -778. 67. Rapps S., Weyuker E. Selecting software test data using data flow information // IEEE Trans. Software Eng. — 1985. —Vol. 11. —P. 367—375. 68 Rosen B. A lubricant for data flow analysis // SIAM J. Comput. — 1982 - Vol 11. P. 493—511. 69. Rosen B. Monoids for rapid data flow analysis// SIAM J. Comput. — 1980 — Vol. 9.— P. 159—196. 70 Ruzicka .1. The use of dominance relations for flowgraph decomposition // Scripta Fac. Sci. Nat. Univ. Purk. Brun. — 1990. — Vol. 20, N 4. — P. 195—201. 71. Ryder B, Pauli M. C. Elimination algorithms for data flow analysis// ACM Computer Sur- veys. — 1986. — Vol. 18, N3. — P 277—316. 72. Shasha D., Snir M. Efficient and correct execution of parallel programs that share memory// ACM Trans. Program. Lang. Syst. — 1988. — Vol. 10 — P. 282—312. 73 Sreedhar V. C., Gao G. R., Lee Y.-F Incremental computation of dommdtor trees // ACM Transactions on Programming Languages and Systems.—1997. — Vol. 19, N 2.— P. 239 — 252. 74 Tamine .1. .1. On the use of tree-like structures to simplify measures of complexity// SIGPLAN Notices. — 1983. — Vol. 18, N 9. — P. 62—69. 75. Tarjan R. E. A class of algorithms which require nonlinear time to maintain disjoint sets// .1 Comput. Syst. Sci. — 1979. — Vol 18, N 2. — P. 110—27. 76. Tarjan R. E., Van Leeuwen J. Worst-case analysis of set union algorithms// .1. ACM. — 1984. — Vol. 31, N 2. — P. 245—81. 77 Tarjan R. E. A unified approach to path problems// J ACM. 1981 Vol. 2. — P. 576— 593. 78. Tarjan R. E. Fast algorithms for solving path problems // .1. ACM 28. — 1981. — P. 594—614 79. Tarjan R. E. Iterative algorithms for global flow analysis // Algorithms and Complexity — New Directions and Recent Results. — New York: Academic Press, 1976. — P. 71—101 80. Tarjan R. E. Depth first search and linear graph algorithms// SIAM J. Comput.— 1972. Vol. 1,N2. P 146—160. 81. Tarjan R. E. Finding dominators in directed graph // Ibid. — 1974. — Vol. 3, N 1. — P. 62— 89.' 82. Tarjan R. E., Valdest J. Prime subprogram parsing of a program // Conf Record of the 7th Ann. ACM Symp. on Principles of Programm. Languages. — Las Vegas, Nevada, 1980. - P. 95— 105. 83 Weiser M Program slicing//IEEE Trans. Software Eng.— 1984 —Vol 10 —P. 352 -357. 84. Whitty R. Object-oriented metrics: an annotated bibliography// SIGPLAN Notices. — 1996. — Vol. 31, N 4. 85 Zadeck F. K. Incremental data flow analysis in a structured program editor // SIGPLAN No- tices. — 1984. — Vol. 19, N 6,— 132—143.
ГЛАВА 1 1 Преобразование программ Проблематика преобразований и оптимизации программ, развитие которой долгое время было связано с автоматизацией программирования методом трансляции, стано- вится особенно актуальной в связи с возрастанием роли |рансформационного подхода к программированию. Трудно переоценить ту роль, которую играют трансформаци- онные методы в создании инструментальных средств поддержки программирования, начиная от простых редактирующих средств и кончая системами трансформационно- го синтеза. Обычно процесс конструирования программ методами преобразований начинается с ее спецификации— формального описания задачи или корректной и максимально простой, но не эффективной версии программы, как правило, имеющей вид рекурсивных уравнений (равенств термов). Затем применяются сохраняющие корректность преобразования программы (или спецификации) с целью повышения ее эффективности, в процессе которых реализуется переход от одной модели программ к другой, например, от рекурсивных программ к итеративным или от последователь- ных программ к асинхронным. При этом результирующая программа корректна по построению. 11.1. Унификация и системы переписывания термов Задача унификации возникает и изучается во многих приложениях, таких как, напри- мер, доказательство теорем, логическое программирование, обработка естественных языков, вычислительная сложность и теория вычислимости. В наиболее общем виде задача унификации формулируется следующим образом. По двум описаниям X и Y определить, можно ли найти объект Z, который удовлетворяет обоим описаниям? Эта задача обычно уточняется как задача нахождения по данным двум термам, содержа- щим переменные, такой подстановки термов вместо переменных, которая превратила бы исходные термы в идентичные Теория СПТ — систем переписывания (подстановок) термов — является мощным и удобным формальным аппаратом, получившим все более широкое применение для решения различных задач математики и программирования. Изучение СПТ берет
Глава 11. Преобразование программ 819 начало от классической задачи алгебры, получившей название проблемы тождеств и связанной с построением разрешающих алгоритмов для эквациональных (алгебраи- ческих) теорий, формулами которых служат равенства термов В дальнейшем сфера применения СПТ расширилась на теории первого порядка, началось использование методов СПТ для автоматического доказательства теорем, имеющего многочислен- ные приложения в программировании: искусственном интеллекте, логическом про- граммировании и т. д. Алгебраические методы спецификации, основанные на задании посредством равенств абстрактных свойств операций, занимают важное место среди средств спецификации программ и данных. СПТ допускают определение операцион- ной семантики таких спецификаций, сопоставляя каждому выражению (терму) це- почку вычислений (редукций), и могут рассматриваться в качестве абстрактного ин- терпретатора языка алгебраических спецификаций. Поэтому к сфере применения СПТ можно отнести синтез, верификацию, оптимизацию и другие области програм- мирования, в которых используются алгебраические методы спецификации. Важной сферой применения СПТ являются программные системы аналитических преобразо- ваний. 11.1.1. Задача унификации Пусть Е — алфавит, образованный элементами попарно непересекающихся множеств переменных V и символов r-арных функций Е„ где r=0, 1,...— арность функции (количество ее "аргументов"). Элементы из Ео называются константами. Множество термов 7(E), переменных К(7) в терме, t е 7(E), вхождений O(t) подтер- мов в терм t е 7(E) и подтерм t/u терма t е 7(E) по некоторому вхождению и е O(f) определяются следующими правилами: □ если t = х е V, то t е 7(E), И(Г) = {х}, O(t) = {е}, где е— пустая последователь- ность, и tie -х; □ если t ~f g Ео, то t g 7(E), V(t) = 0, O(t) = {e} и tie =f □ если t=flt\,..., 7„), где /g E„ и t\,..., t„ g 7(E), to t g T(Z), f называется внешним (корневым) символом терма t, V(t) = uK(t,), ()(t)= {e} u {iu: и g 0(6)}, где iu j=l обозначает конкатенацию i с последовательностью и, tie =J[t\,..., t„), t/iu = t/u. Для любых s, t g 7(E) и и g O(t) через t[u <- 5] обозначается терм, полученный в ре- зультате замены в терме t подтерма t/u на терм s. Рассмотрим терм t =flh(g(x), уу), уу), I, h(y, z))). Здесь и в дальнейшем х, у, z — пере- менные, afh,g,l — функциональные символы. Для t имеем V(t) = {х, у, z} и O(t) = = {е, 1, 2, 3, 11,12, 32, 31, 111}, причем tie = t, t/l = h(g(x),y), till =g(x), 7/111 =x и z[3 <- g(/)] =/(/r(g(x),yy), /, g(/)). Терм t g 7(5) называется линейным, если каждая переменная из Р(7) встречается (тек- стуально) в терме t один раз (т. е. для любых W|, и2 е O(t), если t!u\ g V, то t/щ Ф t/u2), и замкнутым, если V(t) = 0.
820 Часть II. Применение графов и граф-моделей Отображение v: V —> ДЕ) называется подстановкой. Подстановку и можно расши- рить на все множество термов ДЕ), определив отображение v' следующим образом: □ если Т = х е И, то v'(0 = 4х); □ если t =f & So, то v'(/) =f □ если t=fit\,..., t„), где/е S„ и q, t„ e ДЕ), to v'(t) =./(vVi), ••, v'(t„)). Терм v'(t) называется результатом применения подстановки v к терму t и обознача- ется через tu. В дальнейшем будем рассматривать подстановки, не тождественные лишь на ко- нечном числе переменных, и обозначать их в виде v = (xi <— х* <— /*) или и = {(гь xi),..., (/*, хА)}, где t, — термы, ах,— попарно различные переменные. Композиция двух подстановок V| v2 — это такая подстановка v3, что v3(/) = V|(v2(r)) для всех t е. Т(У). Два терма s и t называются унифицируемыми, если существует такая подстановка v (так называемый унификатор), которая делает указанные два терма идентичными, т. е. 5О - tu. Унификатор и термов хи / называется их наибольшим общим унификато- ром (НОУ), если для любого другого унификатора 0 термов хи/ найдется такая под- становка q, что q-v = 0. Если термы унифицируемы, то существует и единственен их наибольший общий унификатор. Например, термы s= fix, g(a,y)) и t =fih(z), g(v, у)) унифицируемы наибольшим об- щим унификатором и = {(h(z), х), (а, и)}. Термы 5 =fig(a, у), х) и t =fih(z), g(y, у)) не- унифицируемы. 11.1.2. Унификация как решение множества уравнений Формула вида s = t, где х / е ДЕ), называется уравнением (равенством), множество решений которого состоит из всех унификаторов термов хи/. Унификатором множества уравнений st = где/ е [ I : А], называется любая подста- новка и, которая является решением каждого уравнения множества. Два множества уравнений называются эквивалентными, если совпадают множества их унификаторов. Множество уравнений S находится в разрешенной форме, если каждое уравнение в S имеет вид х, = /,, а каждая переменная х}, образующая левую часть одного из уравне- ний в S, не имеет других вхождений в термы из S. Множество уравнений S= {х7 = q : у е [1 : А]}, представленное в разрешенной форме, имеет унификатором подстановку v = {(q, хД, ..., (ф хД}, которая является наиболь- шим общим унификатором у S; любой другой унификатор о множества 5 может быть получен объединением v и а (т. е. о = v и а), где а — подстановка, не затрагиваю- щая переменных Х|.х*.
Гпава 11. Преобразование программ 821 Пусть S'— некоторое множество уравнений. Замена в S некоторого уравнения Д/ь t„) =j{s\,..., s„), где n > 0, на и уравнений tj = sp j е [1 : и], называется редукцией термов. Если п = 0, то редукция термов озна- чает простое удаление уравнения f=f. Пусть х = t— одно из уравнений S. Тогда переход от S к множеству уравнений, полу- чающихся применением подстановки и = {(/, х)} ко всем термам уравнений, отлич- ных от данного (без уничтожения уравнения х = t), называется преобразованием эли- минации переменной. А. Пусть множество S содержит уравнение fis\, ..., s„) = g(p,..., t,J. Если gAf mo S не имеет унификатора', в противном случае S эквивалентно множеству уравнений, получающемуся из S применением к данному уравнению преобразования редукции термов. Б. Пусть S'—множество уравнений, полученное применением преобразования эли- минации переменной к некоторому уравнению х — t множества S. Если переменная х входит в терм t (но t не является переменной х), то S не имеет унификатора', в про- тивном случае S и S' эквивалентны. Алгоритм 11.1. Решение множества уравнений Дано. Множество уравнений S. Требуется. Перевести S в разрешенную форму. Решение. проц НОУ(8: система уравнений) = 1. пока истинно условие применимости хотя бы одного преобразования цикл 2. выбор любого преобразования с истинным условием применимости из 3. Преобразование А: если существует уравнение вида t = х, где t не является переменной, ах — переменная 4. то заменяется это уравнение на уравнение х = t все, 5. Преобразование В: если существует уравнение вида х = х, где х — некоторая переменная 6. то удаляется это уравнение из S все, 7. Преобразование С: если существует уравнение вида Г = t", в котором V и t" не являются переменными 8. то если корневые функции из термов Г и t" различны, то возврат 'неудача' 9. иначе осуществить редукцию термов все все, 10. Преобразование D: если существует уравнение вида х = t такое, что переменная х не входит в другие уравнения системы S и терм t отличен от х 11. то если переменная х входит в t то возврат 'неудача' 12. иначе осуществить элиминацию переменной все все все все;
822 Часть II. Применение графов и граф-моделей 13. возврат'успех' все В качестве примера рассмотрим следующую систему уравнений: S= {g(x2) =Х|, J[x\, Л(.Х|), х2) =./(g(x3), х4, х3)}. Возможна следующая последовательность шагов алго- ритма. Применение преобразования С ко второму уравнению преобразует S' в множе- ство (gfe) = Х|, Х| = g(x3), Л(х|) = х4, х2 = х3}. Это множество в результате применения преобразования D ко второму уравнению примет вид {g(x2) = g(x3), Х| = g(x3), A(g(x3)) = х4, х2 = х3}. Затем можно применить преобразование С к первому уравнению и преобразование А к третьему; в результате получается множество {х2 = х3, х, = = gfeG х4= ^(g(x3)), х2 = х3}. Наконец, применяя преобразование D к первому уравне- нию и преобразование В к последнему, можно получить {х2=х3, X|=g(x3), х4= Mgfe))}, к которому уже ни одно из преобразований А, В, С, D не применимо, и таким образом завершить выполнение алгоритма с успехом. В. Алгоритм 11.1 останавливается всегда, вне зависимости от того, как реализует- ся выбор в операторе 2-14. Г. Алгоритм 11.1 завершается с неудачей, если исходное множество уравнений S не имеет унификатора. Если алгоритм завершается успехом, то S преобразуется в эквивалентное этой системе множество уравнений, имеющее разрешенную форму. 11.1.3. Мультиуравнения и алгоритмы их решения Формула вида S= М, где S— непустое множество переменных, а М— произвольное семейство термов, отличных от переменных, называется мультиуравнением, левой частью которого является S, а правой — М. Решением (унификатором) мультиурав- нения S= М называется любая подстановка, делающая идентичными все термы из S и М. Например, мультиуравнение {хь х2, х3} = (Л(с), а) не имеет унификатора. Пусть SE— некоторое множество уравнений, и пусть отношение /?\7. на множестве пар термов определяется таким образом, что t\Rsnh тогда и только тогда, когда t\ = t2 принадлежит SE. Говорят, что множество SE соответствует мультиуравнению S = М, если все термы SE принадлежат S u М и для всех tr, t, е S и М справедливо trRSf;t, где RSE обозначает рефлексивное, симметричное и транзитивное замыкание отношения Rse. Например, множество уравнений {xi = х2, x3=xl,tl= Х|, х2 = t2, = i2}, соответствует мультиуравнению {xi,x2, х3} =(Ji, t2). Аналогичное определение может быть сформулировано для множества мультиуравнений Z, если рассмотреть отноше- ние Rz между парами термов, которые принадлежат одному и тому же мультиуравне- нию. Множество уравнений SE соответствует множеству мультиуравнений Z, если Г, RSEtj тогда и только тогда, когда t, Rztj для любых термов t„ tj из SE и Z. Преобразования мультиуравнений Пусть М— семейство термов (отличных от переменных или нет). Общей частью М называется терм, который получается путем совмещения всех термов из М, начиная с их корня, и взятия той части, которая является общей для всех из них. Например,
Гпава 11. Преобразование программ 823 для семейства термов (/(х,, g(a,/x5, b))), fih(c), gix^fib, х5))),Дй(х4), g(x6, х3))) общей частью является терм/(х|, g(x2, х3)). Границей М называется множество мультиуравнений, в котором каждое мульти- уравнение ассоциируется с некоторым листом общей части и состоит из всех подтер- мов (один для каждого терма из М), соответствующих этому листу. Для описанного семейства термов граница имеет вид {{хД = (Л(с), й(х4)), {х2, х6} = (а), {х3} = = (Лх5, b\j{b, х5))}. Для нахождения общей части и границы множества термов М можно воспользоваться следующей функцией (вычисляемый ею результат— это либо "неуспех", если М не имеет ни общей части, ни границы, либо пара (С(Л7), F(M)), где С(Л7) — общая часть М, a F(M) — граница М\ функ ДЕС(/И : множество термов) = 1. если существует такой терм t в М, который является переменной то 2. Пусть R обозначает мультиуравнение, чья левая часть — это множество всех переменных из М, а правая часть — семейство всех тех термов из М, которые не являются переменными; 3. возврат <t R) 4. иначе если внешним символом всех термов из М является один и тот же функциональный символ f е Ал 5. то если л = 0 то возврат (f, 0> 6. иначе если для всех i е [1 : л] не является неуспешным применением функции ДЕС к множеству /И, = ш {t,: t = f(fi.........ti, ..., tn) e M} 7. то возврат ..............C(/Mn)), u {F(Mi): i e [1 : n]}) 8 иначе возврат 'неуспех' все все 9. иначе возврат 'неуспех' все все все Пусть Z— множество мультиуравнений, содержащее такое мультиуравнение S = M, что М не является пустым и имеет общую часть С и границу F. Тогда редукция мультиуравнения S- М в Z состоит в переходе к такому Z', что Z'= (Z — {S= Л/}) и u{S = (Q}uF. А. Пусть S= М, где М А 0 — некоторое мультиуравнение из множества Z. Если М не имеет общей части либо некоторая переменная из S входит в левую часть неко- торого мультиуравнения границы F семейства М, то Z не имеет унификатора', в противном случае Z эквивалентно множеству Z', получаемому из Z редукцией муль- тиуравнения S = М. Множество мультиуравнений Z называется компактным, если множества левых час- тей уравнений из Z попарно не пересекаются.
824 Часть II. Применение графов и граф-моделей Пусть Z — некоторое некомпактное множество мультиуравнений и пусть R — отно- шение между парами уравнений из Z такое, что (S = М) R (S' = М') <-> S п 5' = 0 и R — транзитивное замыкание R. Переход от Z к эквивалентному ему множеству Z', в котором слиты (путем объединения их левых и правых частей) все уравнения, при- надлежащие одному и тому же классу эквивалент пости относительно R, называется преобразованием компактификации. Решение систем мультиуравнений Системой мультиуравнений R называется пара (Т, U), в которой Т является такой последовательностью, a U таким (возможно пустым) множеством мультиуравнений, что справедливы следующие три свойства: Г) множества переменных, образующих левые части всех мультиуравнений как в Т, так и в U, содержат все переменные и не пересекаются; □ правые части всех мультиуравнений в Т состоят из не более чем одного терма; П переменные, входящие в левую часть некоторого мультиуравнения из Т, могут входить в правые части только таких мультиуравнений из Т, которые предшест- вуют данному. Алгоритм решения некоторой данной системы мультиуравнений R работает следую- щим образом. Начиная вычисление с пустой части Т и выполняя на каждом шаге "пе- ремещение" некоторого мультиуравнения из {/-части, являющейся неразрешенной частью системы R, в /"-часть, которая называется триангулярной (разрешенной) частью R, алгоритм завершает свою работу в тот момент, когда пустой становится {/-часть системы R. В этот момент система, по существу, решена, поскольку ее реше- ние получается обратной подстановкой переменных. Следует заметить, что хранение разрешенной системы в триангулярной форме позволяет эффективно осуществлять унификацию даже тогда, когда наибольший общий унификатор имеет размер, экспо- ненциальный относительно размера исходной системы. Например, наибольшим общим унификатором системы {{xj = 0, {х2} = 0, {х4} = (h(xj, h(x2, х2)), Л(Л(Л(Х|,Х|), х2), х3)), {х3} = 0} является {(/?(X|, xj, х2), (h(h(xt, xt), h(x}, х,)), х3), (h(h(h(x\, Х|), h(x\,X\)), Л(/г(л-|, Х|), Л(.Т|, Х|))), х4)}. Однако мы можем дать эквивалентную разрешенную систему с пустой {/-частью, у которой /"-часть имеет вид ({х4} = (Л(х3, х3)), {х3} = = (Л(х2, х2)),{х2} = (/?(%!, X])), {х|} =0) и может использоваться для получения наи- большего общего унификатора с помощью обратной подстановки. функ РЕШЕНИЕМ: множество мультиуравнений) = 1. Пусть R = (Г, U) — система мультиуравнений, в которой Г = 0 и U = Z; 2. повторять Пусть S = М — такое мультиуравнение в U, что М * 0; 3. Вычислить общую часть С и границу F множества /И; 4. если левые части границы F содержат некоторую переменную из S то 5. возврат 'неудача' все; 6. Преобразовать U, осуществляя в нем редукцию выбранного мультиуравнения и его компактификацию;
Глава 11. Преобразование программ 825 7. Пусть S = {х-i, хп}. Применить подстановку и = {(С, х-,). (С, хп)} ко всем термам правых частей мультиуравнений Г; 8. Перенести мультиуравнение S = (С) из U в конец Г; 9. до 17-часть системы R содержит только такие уравнения, если они есть, у которых пустые правые части все 10. Перенести все мультиуравнения из U (все с М = 0) в конец Г; 11. возврат'успех' все Понятно, что для того, чтобы использовать алгоритм для унификации двух термов и /2, следует построить начальную систему мультиуравнений {{х} = (гь Л>), {xj = 0, {х2} = 0,..., {х„} = 0}, где Х|,..., х„ — все переменные, входящие в Г и t2, а х — новая переменная, не имеющая вхождений в Г и /2. Например, в процессе обработки термов Z| = /(xi, g(x2, х3), х2, b) и t2 =fig(h(a, х5), х2), Х|, /?(«, х4), х4)) алгоритм проходит следующие состояния. Начальная система мультиуравнений R имеет вид: U : {{х} = (fix\, g(x2, х3), х2, Ь), х5) х2), хь h(a, х4), х4)), {х,} = 0, {х2} = 0, {х3} = 0, {х4} = 0, {х5} = 0}; Т: (). После первой итерации цикла 2—9 она примет вид: U: {{xi} = (g(h(a, х5), х2), g(x2, х3)), {х2} = (h(a, х4)), {х3} = 0, {х4} = (Ь), {х5} = 0}; Т \ ({х} = (Дхь хь х2, х4))). Элиминация переменной х2 приводит к виду: U : {{xj = (g(/j(t/, х5), Л(а, х4)), g(h(a, х4), х3)), {х3} = 0, {х4} = (Л), {х5} = 0); Т: ({х} = (Дх|, хь х2, х4)), {х2} = (/г, (а, х4))). Элимина- ция переменной Х| преобразует R к виду: U: {{х3} = h(a, х4)), {х4, х5} = (Л)}; Т: ( {х} = = (/[хь Х|, х2, х4)), {х2} = h(a, х4)), {х-|} = g(A(a, х4), х3))). Наконец, путем элиминации сначала множества {х4, х4}, а затем {х3} R принимает разрешенную форму: U : 0; Т : ({х} = (Ах,, X,, х2, х4)), {х2} = (Л(д, х4)), {х,} = (g(/z(a, х4), х3)), {х4, х5} = (Ь), {х3} = Л(«, Ь))). Б. Алгоритм РЕШЕНИЕ всегда останавливается. Если он завершается с неудачей, то исходная система не имеет унификатора. Если же он завершается с успехом, то результирующая система эквивалентна исходной системе и имеет пустую не- разрешенную часть. Пусть R— некоторая система мультиуравнений и пусть Vy— подмножество пере- менных, полученное обединением всех левых частей S, мультиуравнений в 77-части системы R. Поскольку множества S, попарно не пересекаются, они определяют раз- биение множества Уи. Отношение < определяется как транзитивное замыкание от- ношения <, удовлетворяющего следующему свойству: для любых двух частей S, и S', справедливо S, < Sj тогда и только тогда, когда найдется такая переменная в S,, кото- рая входит в некоторый терм правой части мультиуравнения, левой частью кото- рого является Sj. В. Если система R имеет унификатор, то < является отношением частичного упо- рядочения. Г. Если система R имеет унификатор и ее U-часть не является пустой, в R сущест- вует мультиуравнение S= М такое, что переменные из S не имеют других вхожде- ний в U.
826 Часть II. Применение графов и граф-моделей функ УНИФИКАЦИЯМ: система мультиуравнений) = 1. Пусть R = (Г, 17); 2. повторять если в 17 не существует такого мультиуравнения S = М, что переменные из S не имеют других вхождений в U 3. то возврат 'неуспех1 4. иначе выбрать одно из таких мультиуравнений S = М все; 5. если М = 0 то перенести это мультиуравнение из 17 в конец Т 6. иначе если М не имеет общей части то возврат 'неудача' 7. иначе вычислить общую часть С и границу F для М все; 8. Преобразовать 17, используя редукцию по выбранному мультиуравнению и компактификацию; 9. Перенести мультиуравнение S = (С) из U в конец Т все 10. до часть U системы R является пустой все; 11. возврат'успех' все Функция УНИФИКАЦИЯ является таким уточнением недетерминированной функ- ции РЕШЕНИЕ, в котором за счет подходящего выбора, обрабатываемого в цикле 2—10 мультиуравнения S=M, ликвидируются операторы 8 и 5. Следует заметить, что оператор 8 функции РЕШЕНИЕ наиболее трудоемкий в ней и может осуществ- лять многократное копирование больших термов. В процессе применения функции УНИФИКАЦИЯ к системе, на основе которой де- монстрировалась работа функции РЕШЕНИЕ, сначала элиминируется переменная х, затем переменная Х|, далее переменные х2 и х3 вместе и, наконец, переменные х4 и х5 вместе. В результате система примет вид: U : 0, Т : ({х} = (/(хь хь х2, х4)), {х1} = = (gte, *з)), {х2, *з} = (h(a, х4)), {х4, х5} = (Л))}. Следует отметить, что это решение, полученное функцией УНИФИКАЦИЯ, является более точным, чем полученное с помощью функции РЕШЕНИЕ. Во-первых, выясне- но, что переменные х2 и х3 эквивалентны, а во-вторых, правая часть с переменной Х| более факторизована. Этот результат не является случайным, а присущ алгоритму УНИФИКАЦИЯ. Суммируя, можно сказать, что алгоритм УНИФИКАЦИЯ основывается на двух иде- ях: хранения решения в факторизованной форме и выбора на каждом шаге такого мультиуравнения, чтобы совсем не требовалось подстановок. В силу этого размер результирующей системы не может превысить ее начальный размер. Более того, опе- рация выбора мультиуравнения завершается неудачей, если есть циклы среди пере- менных; и таким образом, так называемая проверка вхождений встраивается в алго- ритм вместо того, чтобы выполняться на последнем шаге алгоритма, как это имеет место в других алгоритмах. Эффективный выбор мультиуравнения Эффективная реализация операции выбора мультиуравнения, "головного" в смысле частичного упорядочения (оператор 2—5 функции УНИФИКАЦИЯ), заданного на
Глава 11. Преобразование программ 827 мультиуравнениях, может быть осуществлена, если ассоциировать с каждым муль- тиуравнением специальный счетчик для хранения числа других вхождений в U пере- менных его левой части. Этот счетчик инициализируется путем начального сканиро- вания всей (/-части. Понятно, что то мультиуравнение, у которого счетчик равен ну- лю, является головным относительно частичного упорядочения. Например, для системы R, рассмотренной ранее, имеем: U: {[0]{х} = (Дх1; g(x2, х3), х2, Ь), fifih(a, х5), х2), хь h(a, х4), х4)), [2]{х,} = 0, [3]{х2} = 0, [1]{х3} = 0, [2]{х4} = 0, [1]{х5} ~0}; Т (). Здесь счетчики, ассоциированные с мультиуравнениями, заклю- чены в квадратные скобки. Поскольку только у первого мультиуравнения счетчик равен нулю, оно и выбирается оператором 2—4. Счетчики других мультиуравнений очевидным образом изменяются (уменьшаются) в тот момент, когда некоторое вхож- дение соответствующей переменной возникает в левой части мультиуравнения гра- ницы, вычисленной оператором 8—10. Когда два или больше мультиуравнения из U сливаются в процессе компактификации, счетчик, ассоциируемый с новым мульти- уравнением, очевидно устанавливается равным сумме значений счетчиков сливаемых мультиуравнений. Следующие шаги алгоритма сначала приводят к системе вида: U {№<} = (g(/?(«,x5), х2), g(x2, х3)), [2] {х2} =(/;(«, х4)), [1]{х3} = 0, [1]{х4} = (Ь), [1]{х5} = 0}; Т : ({х} = (/(хь хь х2, х4))). Затем получаем: L7: {[0]{х2, х3} = (h(a, х4), h(a, х5)), [ 1 ]{х4} = (Ь), [1]{х5} = 0}; Т: ({х} = (Дхь х,, х2, х4)), (g(x2, х3))). После этого имеем: U : {[0] {х4, х5} = (6)}; Т: ({х} = (fix\, хь х2, х4)), {х,} = (g(x2, х3)), {х2, х3} = = (/г(п, х4))). Результат имеет вид: U: 0, Т: ({х} = (fixt, хь х2, х4)), {xt} = (g(x2, х3)), {х2, х3} = (Л(а, х4)), {х4, х5} = (Л)). 11.1.4. Улучшение алгоритма унификации при обработке неунифицируемых данных В случае неуфицированных данных результатом алгоритма УНИФИКАЦИЯ является неуспех, выданный оператором 4, если найден цикл, либо оператором 9, если возни- кает несовместимость. Неудачу последнего вида можно обнаружить на более ранней стадии унификации без изменения структуры алгоритма. Введем следующее определение. Два терма называются согласованными тогда и только тогда, когда либо хотя бы один из них является переменной, либо они оба не- тривиальные термы, имеющие один и тот же корневой символ и попарно согласован- ные аргументы. Термы, число которых больше двух, называются согласованными, если они все попарно согласуются. Например, три терма fix, g(a, у)), fib, х) и fix, у) согласуются, но не являются унифицируемыми. Можно рассмотреть такую модель функции УНИФИКАЦИЯ, в которой для каждого мультиуравнения все термы, находящиеся в его правой части, согласуются. Эта новая версия является корректной, поскольку, если найдется пара несогласуемых термов в одном и том же мультиуравнении, эти термы никогда не унифицируются. Действуя этим способом, имеющиеся несоответствия алгоритм обнаружит на более ранней стадии Действительно, функция УНИФИКАЦИЯ может обнаружить несоот- ветствие лишь в момент вычисления общей части и границы правой части выбранно-
828 Часть II Применение графов и граф-моделей го мультиуравнения, в то время как в новой версии это несоответствие обнаружива- ется на фазе компактификации, осуществляемой на предыдущей итерации основного цикла Для эффективной реализации проверки согласованности при слиянии двух мульти- уравнений можно использовать представление правых частей мультиуравнений в ви- де мультитермов, определяемых по следующим правилам. Мультитперм либо является пустым, либо имеет вид Д/’i,..., Р„), где /е и Р„ i е [1 : и], есть пара (S„ М, ), состоящая из множества переменных S, и мульти- терма М„ которые не являются пустыми одновременно. Например, семейство термов (fix, g(a, x), F(x,yJ) можно представить мульти- термом Л< W, Ъ), {.г,у}, g«0, a), <£r}, 0)))- Представление правых частей таким способом не приводит к потере информации, поскольку единственными операциями, которые необходимо выполнять над правыми частями, являются операция слияния двух правых частей и операция вычисления об- щей части и границы, а их можно переформулировать следующим образом: функ СЛИТЬ(Ч М2 мультитерм) = 1. выбор Ч из 2. 0: возврат /И2; 3 М]>,.... (Sn1, м„1»: выбор М2 из 4. 0: возврат Ч; 5. f2((Sf, 42), ...,(S„2 /И„2)): если f' = f2 и для всех i е [1 : л] слияние СЛИТЬ (/И,1, /И,2) не завершается неудачей 6 то возврат /‘,«S11 ш S21, СЛИТЬ (Ц1, /И2)>, .... <sn1 u s2, слить (Ч1. Ч2)» 7. иначе возврат 'неудача' все все все все; функ ОБЩАЯ-ЧАСТЬ(/М : мультитерм) = 1. Пусть М = f((St, Mi),.... (S„, M„)); 2. для всех i из [1 : п] цикл 3. если S, = 0 то Р, := ОБЩАЯ-ЧАСТЬ(/М,) иначе Р, := э S, все все; 4. возврат .... Рп) все; функ ГРАНИЦА(/И : мультитерм) = 1 . Пусть М = f«Si, Mt), .... <S„, ч»; 2 . для всех / из [1 : п] цикл 3 если S/ = 0 то Fi := ГРАНИЦА(Ч иначе Р, := {S, = М,} все все 4 возврат Р, ш F2 о ... и Fn все
Глава 11. Преобразование программ 829 Следует отметить, что общая часть и граница определяются только для непустых мультитермов и они всегда существуют. 11.1.5. Алгоритм проверки унифицируемости, основанный на представлении термов дэгами Естественно представлять термы ориентированными деревьями, вершины которых помечены переменными и символами функций. Однако при таком представлении экспоненциально растет размер деревьев, которые можно ожидать в качестве резуль- тата унификации. Например, множество пар термов {(/7(х], Х|), х2), (F(x2, х2), х3), ..., {F(xn_t, х„_|), х,,)} унифицируемо, но образ х„ в наибольшем унификаторе — это терм, получаемый последовательностью подстановок х„ <— Г(хп-Ь х„_|), х„.| «— F(x„ 2, х„ 2), ..., х2 «— F(X|, Х|) и, таким образом, содержащий 2" 1 вхождений х,. Более экономное представление множества унифицируемых термов основывается на ориентированных ациклических графах (дэгах), позволяющих представлять единст- венным подграфом общие подвыражения термов. Например, множество пар термов {(^(хь х2), F(G(x2),G(x3)))} и их наибольший общий унификатор представляются дэгами (рис. 11.1). Рис. 11.1. Дэги множества пар термов и их НОУ В дэге вершина, помеченная Л-арным функциональным символом (А > 0), называется функциональной вершиной и имеет степень исхода А; при k > 1 исходящие из нее дуги различаются, а вершины, в которые они заходят, называются соответственно первым сыном, вторым сыном и т. д. Вершина, помеченная переменной, называется перемен- ной вершиной и имеет степень исхода 0; в дэге есть только одна переменная вершина для каждой переменной. Любая вершина дэга, не имеющая заходящих дуг, называет- ся корнем. Отношение эквивалентности, заданное на вершинах дэга, называется допустимым. если справедливы следующие три условия: П соответствующие сыновья двух функциональных вершин попарно эквивалентны; П каждый класс эквивалентности является гомогенным, т. е. он не содержит двух вершин с различными функциональными символами;
830 Часть II. Применение графов и граф-моделей П классы эквивалентности могут быть частично упорядочены частичным порядком на дэге. Первые два из этих условий гарантируют то, что при стягивании каждого класса эквивалентности в вершину вершины результирующего редуцированного графа мо- гут быть согласованно помечены символами подходящей арности, а последнее — это условие ацикличности редуцированного графа. А. Вершины и и v унифицированы тогда и только тогда, когда u&v для некоторого допустимого отношения эквивалентности. Если это так, то имеется единственное минимальное допустимое отношение эквивалентности. На его основе можно сформулировать следующий алгоритм проверки унифицируе- мости двух термов: функ TECTfu, v: терм) = 1. Представить и и v дэгом и установить u=v; 2. пока существует в дэге такая пара вершин и и v, что и = v и для некоторого i нет отношения эквивалентности между i-ми сыновьями и' и v' вершин и и v 3. цикл установить, что и' = v' все; 4. если отношение эквивалентности "=" допустимо то 5. возврат 'унифицируемы' 6. иначе возврат 'неунифицируемы' все все Корневой класс — это класс эквивалентности вершин дэга, содержащий только корни. Б. Любое непустое отношение эквивалентности, удовлетворяющее третьему усло- вию в определении допустимости, имеет корневой класс. На основе свойства 11.1.5, Б алгоритм проверки унифицируемости можно перефор- мулировать следующим образом: функ ТЕСТ1(и, v: терм) = 1. Построить дэг по и и v и установить и = v; 2. НОУ = 0; % наибольший общий унификатор % 3. пока существует корневой класс R цикл 4. если R не гомогенный то возврат 'неунифицируемы' все; 5. Пусть R = {л, ..., р], где, если R содержит функциональную вершину, то ri является функциональной вершиной; 6. для i от 2 до к цикл 7. если п является переменной вершиной то НОУ <- (л <- л) 8. иначе для j от 1 до | ИСХОД (л)| цикл 9. Установить эквивалентность j-x сыновей вершин г, и л все все все;
Гпава 11. Преобразование программ 831 10. Уничтожить все вершины из R вместе с исходящими из них дугами все; 11 возврат если есть дуги то 'неунифицируемы' иначе 'унифицируемы' все все 11. 1.6. Линейный алгоритм унификации Патерсона — Вегмана -------3 адач а---------- Объекты. Рассматриваются дэги, представляющие термы (см. разд. 11.1.5). Каждой вершине дэга сопоставляются следующие атрибуты: СИМВОЛ, значением которого является функциональный символ или символ переменной; УКАЗ, значением которо- го является имя любой вершины; ОТЦЫ, представляющий собой список отцов вер- шины; ДУГИ, являющийся списком неориентированных дуг, инцидентных данной вершине, а также (если вершина функциональная) атрибут СЫНЫ, представляющий собой массив имен сыновей вершины. При этом каждая вершина и каждая дуга дэга могут находиться в одном из двух состояний: "существует" и "удалена". Операции. Операция СОЗДАТЬ-ДУГУ соединяет неориентированной дугой две указанные вершины дэга, а операции УДАЛИТЬ-ДУГУ и УДАЛИТЬ-ВЕРШИНУ переводят в состояние "удалена" соответственно указанную неориентированную дугу или указанную вершину вместе с инцидентными ей дугами. Дано. У любой вершины не определено значение атрибута УКАЗ и пуст список ДУГИ; выделены две вершины и и v. Требуется. Проверить, являются ли унифицированными термы, соответствующие деревьям с корнями и и v, а в случае их унифицируемости построить наибольший общий унификатор. ------ Решение------ Метод. проц ФИНИШ(г: вершина) = 1. S : стек вершин = 0; 2. если г.УКАЗ * <2 то вывод неудача : цикл'; стоп 3 иначе г УКАЗ := г, S < - г, 4. пока S/0 цикл 5. s э S; 6. если /".СИМВОЛ и з.СИМВОЛ — различные функциональные символы 7 то вывод 'неудача.конфликт'; стоп все, 8 для всех существующих / из s-ОТЦЫ цикл ФИНИШ(/) все; 9. пока существует (s, /) из ДУГИ(в) цикл 10. если /.УКАЗ = О то /.УКАЗ := г все; 11 если / УКАЗ * / то вывод 'неудача.цикл'; стоп все;
832 Часть II. Применение графов и граф-моделей 12. УДАЛИТЬ-ДУГУ(5, t); S <- t все; 13 если s* сто 14 если s СИМВОЛ — переменная то вывод (s, г) 15. иначе для j от 1 до | ИСХОД (s)| цикл 16. СОЗДАТЬ-ДУГУ(г.СЫНЫ И.я.СЫНЫ [/]) все; 17 УДАЛИТЬ-ВЕРШИНУ(з); все все все; 18 УДАЛИТЬ-ВЕРШИНУ (г) все все; проц ТЕСТ2(и, v: вершина) = 1. Пусть ФВ и ПВ — списки функциональных и переменных вершин соответственно; 2. СОЗДАТЬ-ДУГУ(ц, v); 3. пока существует г из ФВ цикл ФИНИШ(г) все; 4. пока существует г из ПВ цикл ФИНИШ(г) все; 5. вывод 'унифицируема' все Данный алгоритм является уточнением алгоритма ТЕСТ, описанного в разд. 11.1.5. Основные шаги алгоритма при обработке пары термов {(zl(Z?(v), C(u, v)), C(w, D(x, yy)))} выполняются в следующей последовательности. Вначале создается дэг и добавляется неориентированная дуга, соединяющая корни (рис. 11.2). Предположим: D(x, у)— первая встреченная функциональная вершина, что отража- ется в иллюстрирующих рисунках добавлением числа 1 в качестве верхнего индекса
Гпава 11. Преобразование программ 833 пометки этой вершины. Тогда указатель вершины устанавливается на нее саму, и осуществляется переход к ее отцу с путем рекурсивного общения к процедуре ФИНИШ. Затем указатель вершины с метится числом 2, и опять происходит рекур- сивное обращение для исследования А, отца вершины с, помечающее А числом 3. (Здесь выбираются числа в качестве указателей в силу их единственности.) Так как у А нет отца, происходит переход к другой вершине А и приписывание ей числа 3. Проводятся неориентированные дуги между соответствующими их сыновьями, уда- ляются вершины А вместе со всеми инцидентными им дугами (удаляемые вершины закрашиваются, а удаляемые дуги изображаются штриховыми линиями) — рис. 11.3. Рис. 11.3. Вид дэга после второго шага Поскольку завершается вызов ФИНИШ(/1), происходит возврат к обработке класса эквивалентности, который в конечном итоге пометится числом 2. Осуществляется переход к другой вершине с, рисуются неориентированные дуги между соответст- вующими сыновьями, удаляются вершины с вместе с инцидентными им дугами — рис. 11.4. Рис. 11.4. Вид дэга после третьего шага 27 Зак. 202
834 Часть II. Применение графов и граф-моделей Происходит возврат к вершине D. Осуществляется прохождение к v, но перед унич- тожением вершины v рассматривается ее отец. Этот шаг алгоритма необходим, чтобы не пропустить тот факт, что Dhv должны унифицироваться с и и w. Он завершается состоянием, представленным на рис. 11.5. Рис. 11.5. Вид дэга после четвертого шага Наконец заканчивается обработка того первого класса, с которого все началось, а также классов, содержащих х и у (рис. 11.6). Рис. 11.6. Результат обработки первого класса А. Временная сложность алгоритма ТЕСТ2 является линейной по отношению к "вершины + дуги" дэга. 11.1.7. Алгоритм Уэ --------------------------Задача--------- Объекты. Рассматриваются дэги, представляющие термы. Каждой вершине сопос- тавляются следующие атрибуты: СИМВОЛ, значением которого является функцио-
Глава 11. Преобразование программ 835 нальный символ или символ переменной; КЛАСС, значением которого является имя вершины, представляющей класс эквивалентности, содержащий данную вершину, и называемой корневой вершиной класса эквивалентности, представленного ею; а так- же, если вершина функциональная, атрибут СЫНЫ, представляющий собой массив имен сыновей данной вершины. Дано. У любой вершины не определено значение атрибута КЛАСС; зафиксированы две вершины и t2. Требуется. Проверить, являются ли унифицируемыми термы, соответствующие вершинам и и t2, и в случае положительного ответа на этот вопрос построить наи- больший общий их унификатор. -------Решение--------------- Метод. функ TECT3(fi, fe : вершина) = 1. ПАРЫ: стек = {(fi. fe)}; 2. для всех вершин z цикл z.КЛАСС := z все; 3. пока ПАРЫ * 0 цикл 4. (х,у) := э ПАРЫ; и ;= найти х; v := найти у; 5. еслии*уто 6. если ^.СИМВОЛ и у.СИМВОЛ — различные символы 7. то возврат 'неудачажонфликт* 8. иначе слить и с V, 9. если ^.СИМВОЛ — переменная то и.КЛАСС := v все; 10. если ни ^.СИМВОЛ, ни у.СИМВОЛ не являются переменными 11. то для j от 1 до | ИСХОД (s)| цикл 12. ПАРЫ <- (ц.СЫНЫЙ, кСЫНЫЙ) все все все все все; 13. Сформировать новый граф, образованный из корневых вершин классов эквивалентности; этот граф является результатом унификации; 14. если граф имеет цикл то возврат 'неудача:цикл' 15. иначе возврат'унифицируемы'; 16. % Наибольшим общим унификатором является подстановка о, которая каждой переменной сопоставляет корневую вершину класса эквивалентности, содержащую эту переменную % все все Алгоритм Уэ является уточнением функции ТЕСТ; он поддерживает множество клас- сов эквивалентности с помощью набора, позволяющего хранить непересекающиеся
836 Часть II. Применение графов и граф-моделей множества и эффективно выполнять над ними операции слить и найти. Сначала ка- ждая вершина образует свой собственный класс, а затем в процессе унификации не- которые из классов объединяются. Если вершины, чьи классы должны объединяться, имеют разные функциональные символы, возникает конфликт, означающий неуни- фицируемость термов. В конце концов, если процесс завершается, классы эквива- лентности, разбивающие множество всех вершин, формируют редуцированный граф, который является результатом унификации. А. Временной сложностью алгоритма Уэ является О(иа(и)), где п — количество вершин, а ос(п) — очень медленно растущая функция Тарьяна. 11.1.8. Сравнение алгоритмов унификации Описанный алгоритм УНИФИКАЦИЯ не является линейным (его временная слож- ность— О(п + те log те), где п— суммарное количество символов в унифицируемых термах, а те — число различных переменных в этих термах) и поэтому уступает по оценкам как алгоритму Уэ, который имеет почти линейную сложность, так и алго- ритму Патерсона—Вегмана, который является линейным, т. е. теоретически наилуч- шим. Вместе с тем в ряде практических приложений, как показывает сравнение этих трех алгоритмов, более эффективным оказывается алгоритм УНИФИКАЦИЯ. Нетрудно видеть, что рассмотрение алгоритмов Уэ и Патерсона—Вегмана как алго- ритмов решения уравнений приводит к следующей их формулировке. Оба алгоритма являются некоторыми уточнениями алгоритма РЕШЕНИЕ и работают с множествами мультиуравнений таких, что их левые части попарно не пересекаются, а правые со- стоят из единственного терма глубины один, имеющего видДхь ..., х„), где хь ..., х„ — переменные. Например, {xj ~Л.Х2, х3, х4); {х2} = а; {x3}=g(x2); {х4} = а; {х5} = =ЛХ6, х7, х8); {х6} = а; {х7} = g(x8); {х8} = 0. Кроме того, рассматривается множество уравнений S, в каждом из которых обе части образованы переменными; например, S': {х, = х5}. Шаг выполнения любого из алгоритмов состоит в выборе одного уравнения из S, слияния двух соответствующих мультиуравнений и добавления новых уравнений, полученных в результате слияния. Например, после первого шага вычисляется со- стояние: {х|, х5} =/(х2, х3, х4}; {х2} = а; {х3} = g(x2); {х4} = а; {х6} = а\ {х7} = g(x8); {х8} = 0; S: {х2 = х6, х3 = х7, х4 = х8}. Алгоритмы различаются способом выбора уравнения из S. В алгоритме Уэ S является списком; на каждом шаге выбирается первый элемент из списка, а новые уравнения добавляются в конец списка S. Алгоритм останавливается, когда S является пустым, и достигает этого состояния без проверки отсутствия циклов. Таким образом, имеется последний шаг, на котором проверяется, являются ли результирующие мультиурав- нения частично упорядоченными. Источник нелинейного поведения этого алгоритма тот же, что и в алгоритме УНИФИКАЦИЯ: доступ к мультиуравнениям после их слияния. Чтобы избежать это- го, Патерсон и Вегман выбирают для слияния два мультиуравнения только тогда, ко- гда их переменные в дальнейшем недоступны. Например, из описанного состояния
Гпава 11. Преобразование программ 837 алгоритм Патерсона—Вегмана переходит к состоянию {хь х5} =Дх2, х3, х4); {х2} = а; {х3, х7} = g(x2); {х4} = а; {х6} = а; {х8} = 0; S : {х2 =х8, х2 =х6, х4 = х8}, выбирая урав- нение х3 = х7, поскольку х2 и х8 еще доступны из третьего и шестого мультиуравнений соответственно. Для того чтобы выбрать мультиуравнения для слияния, этот алгоритм "поднимается" по частичному упорядочению мультиуравнений до тех пор, пока не находит мульти- уравнения, находящегося "наверху". Таким образом, обнаружение циклов присуще этому алгоритму. Для сравнения рассмотрим, как работает алгоритм УНИФИКАЦИЯ для того же при- мера. Начальная система мультиуравнений примет вид U: {[0]{хьх5} 0), <{х3, х7}, 0>, <{х4, х8}, 0» [2]{х2} =а, [1]{х3} =g«{x2}, 0», [ 1 ]{х4} = а, [1]{х6} = а, [1 ]{х7} = g«{x8}, 0», [2]{х8} = 0,}; Т: (). На следующем шаге: U : {[1 ]{х2, х6} = а, [0]{x3,x7} =g«{x2,x8}, 0», [1]{х4, х8} = о}; Т; ( (){хьх3} =Дх2, х3, х4)), и т. д. В этом алгоритме уравнения, содержащие те пары переменных, которые будут уни- фицироваться, хранятся в мультиуравнениях, и слияния осуществляются до элимина- ции соответствующего мультиуравнения. Важным отличием алгоритма УНИФИКАЦИЯ от двух других является то, что он может использовать термы произвольной глубины. Это приводит к некоторому выиг- рышу с точки зрения эффективности, поскольку очевидно проще вычислять общую часть и границу глубоких термов, чем последовательно сливать мультиуравнения. Следует отметить, однако, что эти возможности можно также добавить к другим ал- горитмам. Например, путем добавления к алгоритму Патерсона—Вегмана способно- сти обрабатывать глубокие термы можно получить линейный алгоритм, известный как алгоритм Мартелли—Монтанари. Для того чтобы сравнить характеристики трех алгоритмов, следует отметить, что каждый из алгоритмов может завершить свою работу либо успешно, либо с неудачей из-за обнаружения цикла или несогласованности. Пусть р„„ рс и р, обозначают веро- ятности остановки алгоритма по этим трем событиям соответственно. Возможны три крайних случая. Случай 1: р,„ » рс, р„ т. е. очень высока вероятность успешного завершения алго- ритма. Асимптотически наилучшим является алгоритм Патерсона—Вегмана, по- скольку он имеет линейную временную сложность, а два других алгоритма— срав- нимую нелинейную сложность. Однако в типичных приложениях, таких как, напри- мер, доказательство теорем, алгоритм унификации не используется для обработки очень больших термов, но для унификации небольших термов в каждой задаче при- меняется многократно. В этом случае асимптоматически растущее различие между линейными и нелинейными алгоритмами не столь существенно, и вычислительные сложности трех алгоритмов будут сравнимыми в зависимости от эффективности реа- лизации. Экспериментальное сравнение трех алгоритмов между собой, выполненное в [42], осуществлено для реализации их на языке Паскаль с использованием подобных структур данных. На пяти различных классах унифицируемых тестовых данных, для которых проводилось сравнение, наименьшее время работал алгоритм УНИФИКАЦИЯ.
838 Часть II. Применение графов и граф-моделей Это объясняется тем, что он, в отличие от алгоритма Уэ, не выполняет в конце про- верку ацикличности и использует более простые структуры данных, чем алгоритм Патерсона—Вегмана. Случай2: рс»р,»р,„, т. е. очень высока вероятность обнаружения цикла. Алго- ритм Патерсона—Вегмана является наилучшим, поскольку он начинает сливать два мультиуравнения только тогда, когда уверен, что среди них нет циклов. Также хорош алгоритм УНИФИКАЦИЯ, поскольку обнаружение цикла в него встроено. В отличие от них алгоритм Уэ должен завершить все слияния прежде, чем он будет в состоянии обнаружить цикл, и, таким образом, он имеет очень низкую производительность Случай 3: pt» Рс» рт, т. е. очень высока вероятность обнаружения несогласован- ности. Алгоритм Уэ является наилучшим, поскольку он останавливается при обнару- жении несогласованности без каких-нибудь затрат на обнаружение цикла. Алгоритм УНИФИКАЦИЯ в этом случае эффективней алгоритма Патерсона—Вегмана, т. к. несогласованности обнаруживаются им во время слияния мультиуравнений и некото- рые мультиуравнения он сливает ранее (подобно {х2, х6} и {х4, х8} в описанном при- мере). С другой стороны, те слияния, которые осуществляются алгоритмом УНИФИКАЦИЯ в процессе размещения их в мультитермах, не могут быть выполне- ны другим алгоритмом, т. к. они ссылаются на мультиуравнения, которые еще дос- тупны. Это различие в производительности двух алгоритмов может быть очень боль- шим, если разрешены термы любой глубины. 11.1.9. Эквациональные спецификации Эквациональной спецификацией (теорией) называется пара (Е, Е), где Е — сигнатура, т. е. алфавит, состоящий из элементов счетного множества переменных и непустого множества функциональных символов, а Е — множество равенств s — t между терма- ми s, t е ДЕ). Например, эквациональной спецификацией аддитивной группы является пара (Еь £(), в которой Е| содержит функциональные символы 0 (нульарный), (унарный), "+" (бинарный), a Et состоит из следующих равенств: 0 + х - х, (-х) + х = 0, (х + у) + z = = х + (у + z), в которых используется инфиксная запись для "+". Пусть (Е, Е) — некоторая эквациональная спецификация, a s = t — некоторое равен- ство между термами s, / е ДЕ). Если s = t выводимо из Е, используется обозначение (Е, £) Н s = I или s = i;t. Выводимость определяется посредством системы следующих правил вывода: I. (Е, Е) I- S = t, если s = t е Е. _ (Е,£) |- s=t 2. ------------------для каждой подстановки о. (Е,£) |- o(s)=o(t) , (Е,£) |- ..........(Е,£) |- s„=t„ 3. -----------!!--------------------— для каждого н-арного функционального (Е,£) |- £(s,,...,«„) = £(/„...,/,,) символа F е Е.
Гпава 11. Преобразование программ 839 4. (E,£)bt=t. 5 (4£) I- г,=г2,-,(Е,£) |- t2=t3 (Е.Е) |- t, = t3 6 (Е,£) |- s = t (Е,£) |- t = s Пусть Е — некоторая сигнатура. ^.-алгеброй называется некоторое множество Ма вместе с функциями f* : М"А —> МА для каждого и-арного функционального символа /g Е; если f— константа, то /еЛД. Например, для эквациональной спецификации аддитивной группы (Еь £|) можно рас- смотреть Е[-алгебру А{, образованную из МА = {а, Ь, с}, константы а и функций —Л| и +А j, определены в табл. 11.1. Таблица 11.1. Экеациональная спецификация Значение функции A — 1 Значение функции a b с a a b с a a ь b с a b c с с a b c b Пусть Е — некоторая сигнатура и А — некоторая Е-алгебра. Всякое равенство s = t между термами из ДЕ) получает значение в А путем интерпретации функциональных символов в з и t соответствующими функциями из А. Переменные в s = t явля- ются (неявно) универсально квантифицированными. Например, значением равенства (-х) + х = 0 в Егалгебре А{ является Vx g A/+^i(-(x), х) = a. Очевидно, что высказывание Vx g MAi + '\(-Л(Х)>х) = а является истинным. Говорят, что равенство выполняется для Аь взятой в качестве интерпретации, a At есть модель равенства (-х) + х = 0 (удовлетворяет этому равенству), и используется обозначение А 1= (-х) + х = 0. Е-алгебра А является моделью множества равенств £ между термами ДЕ) (обозначе- ние A 1= £), если каждое равенство s = t из £ выполняется для А. Пусть (Е, £) — эквациональная спецификация. Говорят, что (Е, £) определяют класс всех Е-алгебр А таких, что А 1= £, и используют обозначение (Е, £) 1= F для множества F равенств между термами из ДЕ), если А 1= F для любой Е-алгебры А, определенной спецификацией (Е, £).
840 Часть II. Применение графов и граф-моделей Проблема тождеств для спецификации (Е, Е) формируется следующим образом: для любого заданного равенства s = I между термами из ДЕ) определить, верно или нет, что (Е, Е) 1= 5 = t. Следующая теорема устанавливает эквивалентность двух рассмотренных подходов к определению семантики эквациональной спецификации: синтаксического (через по- нятие выводимости) и семантического (через понятие модели). Теорема Биркхоффа. Пусть (Е, £) — некоторая эквациональная спецификация. Тогда для любых термов s и t из ДЕ) справедливо (Е, Е) )- s = t в том и только в том случае, когда (Е, Е) 1= s = I. Существуют неразрешимые эквациональные теории, для которых проблема тождеств алгоритмически неразрешима. Например, не существует алгоритма, доказываю- щего или опровергающего равенство любых двух термов, построенных из бинарной операции (применение) и констант S, К, 1, относительно следующего множества равенств (так называемая комбинаторная логика): ((S • х) • у) • z = (х z) (у z), (К х) у~= х, 1 • х = х. 11.1.10. Понятие системы переписывания термов Пусть Е — некоторая сигнатура. Правилом переписывания термов над Е называется такая упорядоченная пара термов s, t е (Е), обычно записываемая в виде s 1, что s g V и V(t) с V(s). Системой переписывания термов (СПТ) называется пара (Е, R), в которой R — некоторое конечное множество правил переписывания над Е. В дальнейшем для обозначения СПТ (Е, R) обычно будет использоваться R, посколь- ку сигнатура Е фиксирована, а правилам переписывания в R иногда будут даваться г имена, например, г в виде г : 5 —> Z или s-^ t. СПТ R порождает на ДЕ) бинарное отношение называемое отношением редук- ции, которое можно определить как множество пар, выводимых из R посредством второго и третьего правил вывода из разд. 11.1.9, в которых символ "=" заменен на Говорят, что терм t\ редуцируется в терм t2 по вхождению и и обозначается t\ —> /2, к если существуют такие и е O(Zi) и (s —> Z) е R, что для некоторой подстановки о справедливо 0(5) = Z/и и /2 = [w <— сг(01- Например, для R = {f(z, h(y)) -> g (h(yj)}, терм = fifia, h(x)), h(b)) редуцируется в терм f(,g(h(x)), h(b)) по вхождению и = 1 и с использованием подстановки о = {(я, z), (х, y)}i а также редуцируется в терм g(A(£>)) по вхождению и = е и с использованием подстановки о = {(/(я, й(х)), х), (Ь, _у)}. Транзитивное, транзитивно-рефлексивное, транзитивно-рефлексивно-симметричное i' * замыкания отношения -> обозначаются соответственно и =. Отношение = Я R R 11 R
Гпава 11. Преобразование программ 841 совпадает с отношением =, где Е получено из R заменой всех правил переписывания на соответствующие равенства; говорят, что СПТ R порождает отношение эквива- лентности = . я Терм t называется редуцируемым (относительно R), если существует такой терм s е ДЕ), что / —> 5, и нередуцируемым (или тупиковым') в противном случае. Если я /—> и л нередуцируемый, то 5 называется нормальной формой терма t и обозначается 5 = t 4- R. Термы 5 и t называются конвергентными, если s 4- R — 14- R. 11.1.11. Свойство Черча — Россера, конфлюэнтность, нетеровость и полнота системы переписывания термов Пусть R — некоторая СПТ. Следующие два эквивалентных свойства R формулируют- ся в терминах отношения =, порождаемого данной СПТ: я П R обладает свойством Черча—Россера, если для любых t\, 13 е ДЕ) выполняется /1 = /2 тогда и только тогда, когда существует /3 е ДЕ) такой, что и R R tf —> к □ R называется конфлюэнтной, если для любых /ь /2, h е ДЕ) таких, что —> t2 R и /j -> 13, найдется терм t4 е ДЕ), для которого /2 -> /4 и t3 -у /4. я я я Свойство конфлюэнтности иллюстрируется на рис. 11.7, б. Здесь и в дальнейшем от- ♦ ношение -> изображено сплошной стрелкой, а отношение — штриховой. R *1 t 4 Рис. 11.7. Свойство конфлюэнтности: а — локальнвя конфлюэнтность, б— конфлюэнтность
842 Часть II. Применение графов и граф-моделей Очевидно, что в случае конфлюэнтной СПТ нормальная форма любого терма, если она существует, является единственной. Условием, гарантирующим ее существование для любого терма, является следующее важное свойство СПТ: R называется нетеро- вой (или конечно завершимой), если не существует бесконечной цепочки редукций ->t2—> tj, —> ... Нетеровая и конфлюэнтная СПТ называется полной (конвергентной, канонической). В случае полной СПТ нормальная форма любого терма всегда существует и единст- венна. Отношение =к в этом случае разрешимо: для выяснения эквивалентности тер- мов необходимо проверить совпадение их нормальных форм. В силу нетеровости СПТ и конечности R процесс нахождения нормальной формы эффективен. А. Свойства конфлюэнтности и нетеровости СПТ являются алгоритмически не- разрешимыми. Б. Разрешима проблема нетеровости в классе СПТ, состоящих из правил, не содер- жащих переменных. 11.1.12. Локальная конфлюэнтность и критические пары Оказывается, что для нетеровых СПТ свойство конфлюэнтности разрешимо. Разре- шающий алгоритм опирается на понятия локальной конфлюэнтности и критической пары. Пусть R — некоторая СПТ. R называется локально-конфлюэнтной, если для любых термов /2, /3 е Т(Д) таких, ♦ * что Zi -» Г2 и —> /3, найдется терм г4 е TCL), для которого f2 h и /3 -> /4. н н н в Свойства конфлюэнтности и локальной конфлюэнтности иллюстрируются на рис. 11.7, б и 11.7, а соответственно. В общем случае локальная конфлюэнтность не означает конфлюэнтности СПТ (рис. 11.8, на котором изображено локально-конфлюэнтное, но не конфлюэнтное от- ношение редукции), однако справедливо следующее утверждение. Теорема Ньюмена. Для нетеровой СПТ свойства конфлюэнтности и локальной конфлюэнтности эквивалентны. Ключевым для анализа локальной конфлюэнтности является понятие критической пары. Пусть 3| -> Г| и s2 —> t2— два правила переписывания из R, которые без потери общ- ности (можно считать) не имеют общих переменных, т. е. Kfci) п И(л2) = 0 (послед- него условия всегда можно достичь переименованием переменных в одном из пра- вил). Пусть и— некоторое такое вхождение терма в что терм si/u не является пе- ременной и унифицируем с з2. Тогда пара термов o(si[w <- Г2]) и o(/j), где о — наиболее общий унификатор 5[/п и з2, называется критической парой R, полученной в результате совмещения правил s2 -> г2 и $! -> /|.
Гпава 11. Преобразование программ 843 \ Рис. 11.8. Локально-конфлюэнтное, но не конфлюэнтное отношение редукции Например, пусть R содержит правила переписывания fifty, z), w) -» fty, ftz, w)) и /(«, у) —> У- Переименовав переменную у во втором правиле, получаем (а, х) —> х. Подтерм fly, z) левой части первого правила унифицируем с левой частью второго; их наиболее общим унификатором является о= {(а, у),(х, z)}. Исходные два правила порождают критическую пару/(х, w) и fia,fix, w)). Содержательный смысл критических пар поясняет тот факт, что для любых двух пра- вил (^i —> /j), (s2 ti) е. R термы р = o(si[w <— /2]) и q = o(?i), образующие критиче- скую пару, являются результатами редукции терма cr(.Si) по вхождениям и и е и при- менения правил s2 —> /2 и 51 -> /1 соответственно (и, следовательно, р = q). Поэтому вполне естественно, что множество критических пар СПТ R дает исчерпывающую информацию для проверки локальной конфлюэнтности СПТ, что подтверждается следующей теоремой. Теорема Кнута—Бендикса—Уэ. СПТ R локально-конфлюэнтна тогда и только тогда, когда для каждой ее критической пары и Г2 существует терм t такой, что -> t и t2 t. к к Таким образом, если СПТ нетерова, то для выяснения локальной конфлюэнтности (а следовательно, конфлюэнтности— теорема Ньюмена, а также полноты) можно применить следующую разрешающую процедуру: для каждой критической пары и t2 СПТ R (их конечное число) сравнить Ц J- R и /2 J- R. В случае совпадения каждой такой пары заключаем, что система конфлюэнтна (т. е. полна); в противном случае — R неконфлюэнтна. Например, пусть R = {(х у) • z —>х (у z)}. Единственное правило в R порож- дает единственную нетривиальную критическую пару Г| = (х • (у • z)) w) и t2 =
844 Часть II. Применение графов и граф-моделей = (х у) (z • w). Так как /, -э х ((у • z) • w)) х (у • (z w)) и /2 -> х • (у (z • w)), то R локально-конфлюэнтна. 11.1.13. Построение полных СПТ для эквациональных теорий Особый интерес представляет задача построения по заданной системе равенств Е та- кой полной СПТ R, что = совпадает с =. В этом случае эквациональная теория раз- решима, поскольку s = t тогда и только тогда, когда 5 -I R = / ф R. Обратное утверждение неверно: существуют разрешимые эквациональные теории Е такие, что нет полных СПТ R, для которых = совпадает с =. Например, это имеет место для так называемой теории АИ, состоящей из законов ассоциативности и идемпотентности: (х у) • z = х (у • z), х • х = х. Теория АИ разрешима, т. к. очевидный алгоритм переводит любой терм / в нормаль- ную форму в которой все скобки расположены слева, а строка, полученная из /' удалением всех скобок, не содержит двух идентичных рядом расположенных под- строк. Однако для АИ не существует полной СПТ R такой, что = совпадает с =; при R е доказательстве отсутствия такой R используется следующая теорема. Теорема Шмитта. Пусть Е— отношение эквивалентности на ТЕ, R — множество правил переписывания термов такое, что R обладает свойствами конфлюэнтности и конечной завершаемости, = совпадает с = и не существует такого конечного подмножества Ro множества R, которое образует полную СПТ и для которого = совпадает с =. Тогда не существует полной конечной СПТ Rt, для которой Rq г. = совпадает с =. «1 Е Теоремы Ньюмена и Кнута—Бендикса—Уэ (см. разд. 11.1.12) уже содержат идею метода нахождения по эквациональной теории Е такой полной СПТ R, что = совпадает с = . Е R Осуществляется ориентация равенств из Е путем их преобразования в правила пере- писывания таким образом, чтобы текущая СПТ была нетеровой. Пусть R, полученная таким образом, является нетеровой СПТ. Множество КП(7?)— критических пар системы R — конечно. Для каждой пары </, .v Т) из КГ!(/?) можно сформировать нормальные формы /' и s' термов I и 5 соответственно. Если для всех (/, л) е КП(7?) справедливо (т. е. ( и s конвергентны), то R является конфлюэнтной, иначе — нет. Если R не является конфлюэнтной, а /' и s'— нормальные формы критической пары, можно попытаться добавить к R либо /'—> s', либо s'-* Повторяя этот процесс, можно надеяться на получение в конце концов конфлюэнтного множества правил
Гпава 11. Преобразование программ 845 переписывания. Если таким процессом достигается множество правил переписывания R', обладающее свойствами конфлюэнтности и конечной завершаемости, R' называ- ется пополнением СПТ R. Указанный метод позволяет осуществить построение полной СПТ для эквациональ- ной спецификации аддитивной группы, рассмотренной в разд. 11.1.9, следующим образом. На первом шаге придается равенствам "разумная" ориентация: ri : 0 + х —> х, г2 : (-х) + х —> О, г3: (х +_у) + z -> х + (у + z). Следует отметить, что ориентация в правилах rj и г2 фиксируется свойствами правил переписывания, что же касается правила г3, то обратная ориентация в ней столь же "разумна". Полученная СПТ R = {гь г2, г3} не является конфлюэнтной. Правила г3 и г2 образуют критическую пару, состоящую из неконвергентных термов (рис. 11.9). ((-x)+x)+z 0+z (-x)+(x+z) Рис. 11.9. Критическая пара правил г3 и г2 Термы этой пары имеют нормальные формы 0 + z и (-х) + (х + z). Все множество кри- тических пар правил гь г2 и г3 состоит из трех: x + zhO + (x + z) для и г3, 0 + z и (-х) + (х + z) для г2 и г3, (х + (у + z)) + w и (х + у) + (z + w) для г3 и г3. В первой и третьей критических парах термы имеют одну и ту же нормальную форму — рис. 11.10. г 1 0+(x+z) -----x+z (x+(y+z))+w г зу x+((y+z)+w) г 3 (x+y)+(z+w) (x+(y+(z+w)) Рис. 11.10. Нормальная форма первой и третьей критических пар
846 Часть II. Применение графов и граф-моделей (-0)+(0+z) Рис. 11.11. Неконвергентная пара правил л и г4 Таким образом, к R добавляется новое правило г4 : (-х) + (х + z) -> z. Полученная СПТ все еще не является конфлюэнтной, поскольку rt и г4 порождают неконвергент- ную критическую пару (рис. 11.11). К R добавляется новое правило г5 : (-0) + z -» z. Правила г2 и г4 порождают еще одну критическую пару (рис. 11.12), термы которой не могут быть редуцированы. В результате к R добавляется правило г6 : (-(-х)) + 0 -> х. Совмещая правила г6 и г3, можно получить термы, изображенные на рис. 11.13. Рис. 11.12. Неконвергентная критическая пара правил Г2 и г4 Рис. 11.13. Результат совмещения правил Ге и Гз Терм (-(-х)) + (0 + z) редуцируется к (-(-х)) + z. В результате к R добавляется пра- вило /-у : (-(-х)) + z -> х + z, которое позволяет упростить правило г6, поскольку (-(- х)) + 0 —> х + 0. Следовательно г6 заменяется на г8: х + 0 -» 0. Совмещение пра- вил rt и г5 дает термы, изображенные на рис. 11.14. Рис. 11.14. Результат совмещения правил Гв и г$ Рис. 11.15. Результат совмещения правил г8 и г? В результате возникает новое правило г9 : -0 -> 0. Теперь правило г5 становится из- лишним, поскольку (—(—х)) + 0 -> х + 0. Если рассмотреть совмещение правил г8 и г7, можно получить результат, приведенный на рис. 11.15.
Гпава 11. Преобразование программ 847 Рис. 11.16. Результат совмещения правил г10 и г2 Получается новое правило Гю :-(-х) -> х, делающее правило г7 излишним, поскольку оно преобразует терм (-(-х)) + z в терм х + z. Совмещение Гю с г2 имеет вид, изобра- женный на рис. 11.16. Критическая пара <х + (-х), 0) не является конвергентной и к СПТ добавляется прави- ло Гц : х + (-х) —> 0. Совмещение правил гн и г3 возможно двумя способами, показан- ными на рис. 11.17. Рис. 11.17. Результат совмещения правил Гц и Гз Результатом совмещения Гц и г3 являются правила Г|2: х + ((-х) + z) —> z, r13 : х + + (у + (—(х + у))) -> 0. Совмещение правил г[3 и г4 может быть осуществлено спосо- бом, изображенным на рис. 11.18. (-х)+(х+(у+(-(х+у)))) -X Рис. 11.18. Результат совмещения правил Лзи г4
848 Часть II. Применение графов и граф-моделей Чтобы сделать конвергентными термы критической пары (-х) + 0 и у + (-(х + у)), к R можно добавить правило г|4: у + (—(х +>’)) ~х Тогда правило г,3 станет излишним, поскольку г14 позволяет преобразовать терм х + (у + (—(х + у))) в терм х +(-х), который в свою очередь с помощью правила гн преобразуется в герм 0. Совмещение правил Г|4 и г4 дает результат, приведенный на рис. 11.19. (-у)+(у+(-(х+у))) (-у)+(-х) -(х+у) Рис. 11.19. Результат совмещения правил г14 и г4 В результате к R добавляется правило rl5 : -(х + у) —>(-у) + (-х), а правило rl4 удаля- ется из R, поскольку оно становится излишним, т. к. с помощью Г|5 можно из терма у + (-(х+у)) получить терм у + ((-у) + (-х)), который в свою очередь с помощью пра- вила Г|2 может быть преобразован в терм -х. В этот момент R является нетеровой, имеет только попарно конвергентные критические пары и, таким образом, является полной. 11.1.14. Методы доказательства нетеровости, основанные на упорядочении Проблема нетеровости СПТ в общем случае является неразрешимой (см. свойство 11.1.11, А), поэтому задача состоит в отыскании набора условий, гаран- тирующих нетеровость как можно более широких классов СПТ. Пусть > обозначает некоторое отношение частичного порядка на множестве T(S), т. е. > — транзитивное, рефлексивное и антисимметричное отношение. Отношение > на- зывается линейным упорядочением на T(Z), если > Z2 или t2 > Z( для любых термов th t2 6 7(S). Как обычно, через > обозначается отношение строгого порядка, т. е. Z| > Z2, если /] > Z2 и ti * z2. Отношение называется нетеровым (или вполне фундированным), если не существует бесконечно убывающих цепей Z( > Z2 > Z3 > ... > t„> ... Под предупорядочением понимаются такие частичные упорядочения >, которые не обязательно удовлетворяют условию антисимметричности, т. е. > Z2 и Z2 > ц могут быть истинными для термов th Z2 таких, что Z, + Z2. С предупорядочением > обычно ассоциируется отношение эквивалентности ~ , связывающее такие Zj и z2, что fj > z2 и Z2 > Z]. Таким образом, предупорядочение является частичным упорядочением тогда и только тогда, когда ~ является отношением равенства. Если > является предупорядо- чением, то используется обозначение t, > t2, если Z| > Z2 и не верно Z, ~ z2.
Гпава 11. Преобразование программ 849 Для предупорядочения > вводится более сильное понятие, чем вполне фунди- руемость: отношение > называется вполне предупорядочением, если для любой бес- конечной последовательности термов t2, ... t„,... существуют такие j и к, что j > к wtt> tk. Очевидно, что предупорядочение является вполне предупорядочением тогда и только тогда, когда оно является вполне фундированным и не содержит бесконечных мно- жеств попарно несравнимых элементов. Предупорядочение >, заданное на множестве Г(Е), называется монотонным, если для всех термов t, s, th ..., t„ и функциональных символов f fill,t, ti+i,t„) >f(tx,..., s, tl+l,..., /„), если t > s. А. Пусть > является монотонным вполне предупорядочением на Т(Е) и пусть R — некоторая СПТ на Z. Если для каждого правила (t —> s) е R и любой подстановки а выполняется fit) > o(.s), то R является нетеровой. Монотонное предупорядочение, которое для заданной СПТ R удовлетворяет условию свойства 11.1.14, А, называется конечно-завергиимым (нетеровым) предупорядочени- ем для R. Отношение > называется редукционным упорядочением, если >— вполне фунди- рованное и монотонное отношение строгого порядка, заданное на Т(Е), такое, что ст(л) > cr(z) при s > t для любых термов s, / е Т(Е) и подстановки ст. Простой способ гарантировать то, что предупорядочение является вполне предупоря- дочением, состоит в требовании выполнения подтермного свойства. Говорят, что отношение упорядочения >, заданное на Т(Е), удовлетворяет подтерм- ному свойству, если/(6, ..., г„ ..., z„) > t, для любого терма//ь б, 1п) е Т(Е). Упрощающим предупорядочением называется монотонное предупорядочение, удов- летворяющее подтермному свойству. Б. Упрощающее предупорядочение на T(fi), где S — конечно, является вполне пред- упорядочением. В. Пусть > является упрощающим предупорядочением на Т(Е) и пусть \succeq явля- ется вполне предупорядочением на Z, удовлетворяющим условию замены операций относительно >, т. е. для любых f, ge S арности пит соответственно и термов Гь..., tm S\,..., sm имеем fit\,..., t„) > g(st,..., s„,), если f= g, n> m и существует набор индексов 1 < /| < ... < jm < п такой, что £ > s, для всех i. Тогда > является вполне предупорядочением. Подтермное свойство не является необходимым условием того, чтобы монотонное упорядочение являлось вполне фундированным. Вместе с тем справедливо следую- щее свойство Г. Если > — линейное монотонное упорядочение на Т(Е), то > является вполне фун- дированным тогда и только тогда, когда > обладает подтермным свойством.
850 Часть II. Применение графов и граф-моделей Пусть > обозначает предупорядоченне, заданное на S. Предупорядочение Крушка- ля > на множестве Г(1.) определяется таким образом, что t=fitx, ..., t„) > s = g(sb s,„) тогда и только тогда, когда справедливо одно из следующих свойств: П s = t; П g и существуют такие индексы 1 <j\< п, что > s, для всех I; □ tj s для некоторого /. Теорема Крушкаля — Наша — Виллиамса. Отношение Крушкаля > является вполне предупорядочением на Т(Е) тогда и только тогда, когда > — вполне пред- упорядочение на Z. Конкретным примером упрощающих упорядочений является класс упорядочений, получивших название упорядочений рекурсивных путей и основанных на следующей идее упорядочения мультимножеств. Пусть > обозначает частичное упорядочение на некотором множестве S. Отношение » на множестве конечных последовательностей элементов из S определяется таким образом, что (гь/„) » (sb..., s,„) тогда и только тогда, когда справедливо одно из следующих условий: П п > 0 и т = 0; П для любого j е [1 : т] существует такое i е [ 1 : п], что t, > sy, П существуют такие / е [1 : /?] иу е [ 1 : т], что Sj » t, (т. е. s7» t, или /, = sy), t, » Sj и (G, t») - ti» (sb ..., s„) - Sj, где формула a-a обозначает такую последователь- ность элементов из S, которая получается из заданной последовательности а уда- лением самого левого вхождения элемента а. Д. Упорядочение мультимножеств » вполне фундировано тогда и только тогда, когда вполне фундировано то упорядочение >, на основе которого оно построено. Упорядочение мультимножеств может быть использовано для построения вполне фундированного отношения на TfL). Пусть >— некоторое частичное упорядочение на множестве Z. Отношение > являет- ся упорядочением рекурсивного пути, если для любых $ = g(sb s„) и t~ flji,..., tm) справедливо t> s. когда выполняется одно нз следующих трех условий: □ /= g и (гь /,„) » (х|,s„); □ f> g и (0 » Oi, '«); П не верно, что f= g или f> g и (tt,..., t,„)»(s'). 11.1.15. Алгоритм Кнута — Бендикса Наибольшую трудность в реализации метода СПТ, описанного в разд. 11.1.13, пред- ставляет проблема поддержания нетеровости расширяющихся множеств правил пе- реписывания. Одним из простых решений этой проблемы является фиксация заранее некоторого конечно-завершимого предупорядочения > для R и добавления нового правила только тогда, когда оно не противоречит заданному предупорядочению. Эта
Глава 11. Преобразование программ 851 идея приводит к следующему алгоритму, предложенному Кнутом и Бендиксом (здесь он представлен в своей простейшей форме): функ ПОПОЛНЕНИЕМ: множество правил переписывания) = 1. Пусть > обозначает конечно-завершаемое предупорядочение для R; 2. Пусть КП — множество критических пар для R; 3. пока КП * 0 цикл 4. <Г, s> := Э КП; Г := Г 4- R; s' := s 4 R; 5. если Г* s'то 6. если a(f') > cr(s') для всех подстановок а то 7. Добавить к КП все критические пары между R и Г -> s’ 8. R<-(f'-»s') 9. иначе если c(s') > <j(f) для всех подстановок с 10. то Добавить к КП все критические пары между R и s' -> Г; 11. 12. иначе возврат ’неудача: встретилось неориентируемое равенство' все все все все; 13. возврат'успех' все Имеется три возможности при выполнении функции ПОПОЛНЕНИЕ: функция за- вершается успешно, цикл выполняется бесконечно, встретилась такая пара термов, которая не может быть ориентирована. Последняя возможность определяет наиболее принципиальное ограничение алгоритма Кнута— Бендикса: нельзя построить пол- ную СПТ для эквациональной спецификации с коммутативными операциями. Однако если функция завершается успешно, то результирующая СПТ является конфлюэнтной. Функция ПОПОЛНЕНИЕ не "упрощает" сами правила переписывания. Но такая оп- тимизация может быть выполнена после завершения функции. СПТ R называется несводимой, если для каждого его правила переписывания s —>t справедливы следующие свойства: I = t4 R и s = s 4 {R- {s —> /}}. Теорема Метивиера. Пусть R является полной СПТ. Тогда существует такая не- сводимая полная СПТ R', что совпадают отношения = и = . R 1С Описанный вариант алгоритма Кнута— Бендикса упрощает правила переписывания сразу, как это возможно. Причина выполнения упрощений во время процесса попол- нения, а не после его завершения — это эффективизация процесса пополнения. Дру- гая оптимизация, реализованная в данном варианте алгоритма, — это инкременталь- ность процесса пополнения, позволяющего не вычислять критические пары между
852 Часть II. Применение графов и граф-моделей теми правилами, которые уже рассматривались на предыдущих шагах работы алго- ритма: функ ПОПОЛНЕНИЕ 1(Е: множество равенств) = 1. Пусть > — редукционное отношение на множестве термов 7~(Х); 2. £о := Е; Ro := 0; i := 0; р := 0; 3. цикл 4. пока Е, * 0 цикл 5. % Редукция равенства % 6. Пусть s = t— некоторое равенство из Е,; 7. s' := s i R,; Г := s Ф R,; 8. если s' = Сто Em := E, - {s = f}; Rm := R,, i := i + 1 9 иначе если (s’ > f)\/(t' > s') to 10. если s'> Сто a := s’; p := f' 11. иначе a := f'; p := s'все; 12. % Добавление нового правила % 13. Пусть К — множество меток правил из г,, чья левая часть s* редуцируется правилом a -» р, скажем, к s*; 14. Ем := E,-{s=f} u {s/f = t* | к e К — номер правила sk-^tk}; 15. р;=р+1; 16. Rm := {/: j'.sj -> tj e R,, j~& К и f/-— нормальная форма терма fy относительно R,о {a-> р}} u {р : a-> р}; 17. Правила, попавшие в /м из R„ остаются помеченными либо непомеченными, а новое правило a -> р является непомеченным; 18. /:=/+1 19. иначе возврат'неудача: встретилось неориентируемое равенство' все; все все; 20. % Вычисление критических пар % 21. если все правила в р помечены то возврат г, 22. иначе Пусть к — номер непомеченного правила в R,; 23. Ец-i — множество всех критических пар получаемых совмещением правила к с любым правилом из р, имеющим номер, не превышающий к; 24. Rm — то же множество, что и R, за исключением того, что в нем правило к помечено; 25. z:=/+1 все все все
Гпава 11. Преобразование программ 853 11.2. Промежуточные представления программ Для повышения эффективности компиляторов используется метод, основанный на переводе входной программы в некоторую промежуточную форму, которая позволяет более успешно осуществлять потоковый анализ и реализовать оптимизирующие пре- образования. Выбор "хорошего" промежуточного представления также чрезвычайно важен и для распараллеливающих компиляторов. Он оказывает сильнейшее влияние на вид, асимптотическую сложность и реализацию оптимизирующих и реструктури- рующих преобразований. Хотя использование промежуточного представления в трансляторе не является обяза- тельным, достоинства подхода, основанного на машинно независимом промежуточ- ном представлении, достаточно велики и включают: □ легкость переносимости: компилятор для другой машины может быть создан на основе имеющегося путем замены в нем постпроцессора (генератора кода); П возможность использования машинно-независимого оптимизатора, работающего над промежуточным представлением. 11.2.1. Требования к промежуточному представлению Требования к промежуточным представлениям программ при оптимизирующей трансляции противоречивы, и при выборе промежуточных представлений необходим определенный компромисс в удовлетворении этих требований. К основным требованиям относятся следующие. Выразимость оптимизации. В частности, это означает, что в промежуточном пред- ставлении должны быть указаны явно многие подразумеваемые действия входной программы (например, по доступу к компонентам составных объектов), а также со- держаться конструкции, которые, хотя они и отсутствуют во входном языке, можно получать в результате преобразований и эффективно реализовывать на ЭВМ. Должна быть возможность осуществлять машинно-ориентированные оптимизации, например, за счет включения в промежуточное представление определенных атрибутов- запросов, входящих в контекстные условия преобразований и описывающих свойства машин, или атрибутов-результатов преобразований, необходимых для конструирую- щих преобразований. Сохранение качества. Нельзя, чтобы переход к промежуточному представлению и последующие преобразования приводили к нарушению или потере свойств програм- мы, позволяющих осуществлять ее эффективную реализацию. Сохранение свойств, присутствующих во входной программе и полезных при выпол- нении оптимизаций.
854 Часть II. Применение графов и граф-моделей Унификация конструкций промежуточной программы по отношению к выбранному набору оптимизаций. Удобство оптимизации с точки зрения простоты алгоритмов ее выполнения. К наиболее распространенным формам промежуточного представления программ (ППП) для последовательных машин относятся синтаксическое дерево, управляющий граф, постфиксная нотация и трехадресный код. Более богатая палитра ППП разрабо- тана для параллельных машин, и число таких представлений постоянно растет. В настоящее время хорошее промежуточное представление для параллельных ма- шин — это представление, удовлетворяющее ряду требований, среди которых выде- ляют следующие: □ исполняемость, т. е. возможность отследить ход исполнения программы; □ наличие свойств структуры данных с механизмом сбора информации о зависимо- стях по данным и управлению; □ представление циклов в явном виде; П поддержка модели памяти с модифицируемым императивным сохранением ин- формации’ □ компактность. Одно из таких представлений — управляющий граф — уже рассматривалось в пер- вых пяти главах книги. Не останавливаясь на нем подробно, подчеркнем лишь неко- торые моменты. Схема Лаврова Информационный граф Рис. 11.20. Si,..., S9 — операторы, а х, iv, z, v, г, и, у— переменные, а — схема Лаврова, б — ее информационный граф
Глава 11. Преобразование программ 855 Управляющий граф программы удовлетворяет практически всем перечисленным условиям, в том числе и условию выполнимости, под которой следует понимать воз- можность отследить ход исполнения программы с помощью моделирования переме- щения фишки по дугам уграфа. Он также служит базисом для более сложных пред- ставлений программ. Здесь следует упомянуть операторную схему над распределен- ной памятью (см. разд. 11.3.5), в которой управляющий граф пополняется явной информацией об использовании результатов (выходных данных) одних операторов в качестве аргументов (входных данных) другими операторами — так называемая информационная связь или информационная зависимость между операндами опера- торов. Эта информация в схеме представляется в виде двудольного информационного графа, вершинами которого служат операнды (входы и выходы) операторов, а дуги соединяют выходы операторов с входами (рис. 11.20). 11.2.2. Граф зависимостей по данным Необходимость более полного учета зависимостей операторов из-за использования общих данных привела к развитию общей концепции зависимости по данным. Без анализа такой зависимости невозможно успешно решать задачу автоматического рас- параллеливания программ. В общем случае встречаются три типа зависимости по данным — истинная (или потоковая) зависимость, антизависимость и выходная зави- симость (или зависимость по выходу). Для каждого типа зависимости определены источник и сток зависимости. Графом зависимости по данным называется ориентированный граф, вершинами ко- торого служат операторы программы, а две вершины S, и S2 соединены дугой (S„ 5)), если существует зависимость одного из перечисленных типов с источником в S, и стоком в Sj. Каждая дуга снабжена метками, определяющими вид зависимости и глу- бину зависимости (для оператора в теле гнезда циклов), т. е. номер цикла, порож- дающего данную зависимость. Дадим более формальное определение зависимости по данным. Будем подразумевать под программой список из А операторов. Пусть S, обозначает /-й оператор в програм- ме (считая их в лексикографическом порядке). Имеющиеся в программе операторы подразделяются на два типа: скалярные и индексированные. Индексированные опера- торы — это те, которые встречаются в теле какого-нибудь цикла или чье исполнение явно либо неявно управляется индексной переменной (например, векторные операто- ры). Все другие операторы — скалярные. Степень оператора в программе есть число различных циклов, окружающих его, или число измерений его операндов. Оператор степени к имеет вид S,{Ib /2,..., 4), где Ij, Lj Ц, — индексная переменная j-vo цикла, а Z, и Ц — нижняя и верхняя границы изменения индексной переменной. Ин- дексированный оператор S,(7|, 72, — , Ik) имеет Пу -1* Np где Nj — Uj — Lj+ 1, различных экземпляров по одному для каждого значения Ij,j = 1,..., к. Первый и последний эк- земпляры оператора степени к имеют вид St{L\, L2,..., Z*) и S£Ut,U2,..., U(), соответст- венно. Всякий раз, когда набор индексов очевиден, вместо S^I\,I2, h) будет упот- ребляться просто Sj. Важным понятием является порядок исполнения двух произвольных операторов. По- рядок исполнения между двумя экземплярами операторов S, и Sj определяется еле-
856 Часть II. Применение графов и граф-моделей дующим образом. Для операторов степени 0 (скалярных операторов) оператор S, ис- полняется прежде Sj (обозначение .S', < St), если / <J, т. е. если S, лексически предше- ствует Sj. Для операторов S, и S, степени к (если операторы имеют разную степень, тогда к ним применим тот же подход, что и в скалярном случае) имеют место сле- дующие три случая: □ если S, и Sj не имеют общих индексов, то S, < 5,, если i < j\ □ если они имеют одни и те же индексы, то (обозначая через S,(h, ik) конкретный экземпляр оператора S, при Д = 4, ...,/* = 4) 5,(4,—, 4) = —,/*), если i<j и существует такое m (0 < m < к), что z) =j, для I = 1, m и /игц < Когда i>j, все так же, но /и < А; □ если S, и St имеют т<к общих индексов и ц =jt (/=1,..., т), то S, < St тогда и только тогда, когда i < j. Определим также множества IN(.S') и OUT(S) входных переменных и выходных пере- менных оператора S, соответственно. Обозначим через OUT (.S', (4, ..., ik)) множество экземпляров переменных (необязательно различных), определяемых экземпляром Sj{i\,..., 4) оператора St. Аналогично, обозначим через IN^Xh, 4)) множество эк- земпляров переменных, используемых этим же экземпляром оператора. Два оператора /2, —> 4) и Sj(J\, J2,..., J*) включены в истинную (информационную или потоковую) зависимость .S', 5 Sj (или, что то же самое, между ними есть информа- ционная связь) тогда и только тогда, когда существуют значения индексов (4, i2,4) и (71»/г» • -,jk) такие, что справедливы два условия: S,(ih i2,..., 4) = Sj(j\,j2, ...,jk), □ оит(эд,...,4)) n lN(SX/„ ...,jk)) * 0. Антизависимость от .S, к St определяется так же, как и потоковая, за исключением того, что второе условие заменяется на 114(5X4. > ik)) OUT(^(/|, ...,jk)) * 0. Анти- зависимость обозначается через S, б Sj. S1:A=B+C S2:B=C+E S3:D=A+B S4:IF D>0 THEN S5:D=B+1 Рис. 11.21. Граф зависимости по данным
Гпава 11. Преобразование программ 857 Выходная зависимость от St к 5, определяется так же, как и потоковая, за исключением того, что теперь второе условие заменяется на ОПТ^ХЛ,..., /*)) n OUT(^(/i, —./*)) * 0- Выходная зависимость обозначается через .S', б° S,. На рис. 11.21 показан пример графа зависимости по данным для множества скаляр- ных операторов. Основным свойством графа зависимости по данным (ГЗД) является следующее: вся- кая бикомпонента (зона) определяет нераспараллеливаемый участок программы. В большинстве случаев ГЗД строится не для всей программы, а только для линейных участков или для циклов. Для построения ГЗД используются специальные тесты, наиболее известными из которых являются тест наибольшего общего делителя (НОД- тест), тест Банержи, омега-тест и др. 11.2.3. Зависимость по управлению Наряду с зависимостями по данным большое значение для решения вопроса о воз- можности распараллеливания того или иного фрагмента программы (например, о возможности векторизации оператора) имеет также зависимость по управлению. Зависимости по управлению порождаются условными операторами и передачами управления. Один из способов учета зависимостей по управлению заключается в том, чтобы представить все передачи управления в виде условных операторов присваива- ния, в которых явно указаны управляющие условия. После этого управляющие усло- вия можно рассматривать как входные выражения. В качестве примера возьмем цикл DO 100 /=1, N IF (A(I).LE.O)GO ТО 100 А(1 + 1) = В(/) + 3 100 CONTINUE Анализируя цикл, записанный в такой форме, трудно определить, можно ли его век- торизовать. Однако если представить его в эквивалентной форме DO 100 /= 1, N BRI = A(I).LE.O IF(.NOTBR1)A(I+1) = B(l)+3 100 CONTINUE то становится очевидным, что зависимости по данным образуют рекуррентность и поэтому цикл не векторизуем. Но следующий, очень похожий цикл уже не содержит рекуррентности DO 100/= 1, N IF(A(l).LE.0)GO ТО 100 А(1) = В(/) + 3 00 CONTINUE
858 Часть II. Применение графов и граф-моделей Превращение всех зависимостей по управлению в зависимости по данным приводит к циклу ОО 100/= 1, Л/ 8R1 = A(l) LE.0 IF(.NOT BR1)A(I) = В(Г) + 3 100 CONTINUE который уже векторизуется. Описанное превращение зависимостей по управлению в зависимости по данным известно как IF-конверсия. Операция /F-конверсии заключается в преобразовании всех операторов, находящихся под управлением оператора IF или передачи управления, в условные операторы. За- тем эти условные операторы по возможности транслируются в такие условные опера- торы, для которых условие становится еще одним входным параметром. К этим опе- раторам применимы описанные методы анализа зависимостей; тем самым условная зависимость становится специальным случаем истинной зависимости. Операция /F-конверсии отнюдь не тривиальна, как показывает следующий пример: ООЮО/=1 100 /F(X(/)G Г. 10) GO ТО 60 Si Д(/) = Д(/)+10 /F(8(/).G7".1O) GO ТО 80 S2 8(/) = В(/) + 100 S3 60 А{!) = В(1) + А(1) S4 80 В(/) = А(Г) + 5 100 CONTINUE Здесь есть два условия, которые мы обозначим через С| и с2: ct = A(I).GT.10 и с2 = B(I).GT. 10. Операторы в цикле управляются этими условиями следующим обра- зом: оператор Si имеет управляющее условие ~,С|, оператор S2 -— "Vi л ~>с2, оператор S3 — С| v (“’С) л -1 с2), оператор S4 — С| v (*1с1 л "Vi) v (-г, л т2). Транслятор должен уметь распознавать тождества и упрощать логические выраже- ния. Например, он должен определить, что условие, управляющее оператором S4, все- гда выполняется и, следовательно, S4 не управляется никаким условным оператором С этой целью транслятор часто снабжается алгоритмом упрощения булевских выра- жений. Так, например, модуль /F-конверсии реального транслятора PFC из универси- тета Райса использует алгоритм Квайна— Маккласки и преобразует последний цикл к следующему виду: ОО/= 1, 100 BR1 =AU).GT.1O St IF(.NOT BRI) A(f) = А(Г) + 10 IF(.NOT.BRV) BR2 = B(l).GT.10 S2 IF(.NOT.BR1.AND..NOT.BR2) B(J) = B(l) + 10 S3 /F(8R1. OR.. NOT. BR2) A(l) = B(l) + A(l) Sa B(l) = A(J) + 5 CONTINUE
Гпава 11. Преобразование программ 859 Если к этому циклу применить анализ зависимостей, предусматривающий дополни- тельно обработку условных присваиваний, то он покажет, что все операторы в цикле можно преобразовать в векторные присваивания или в условные векторные присваи- вания. Принципиально иной подход к изучению зависимости по управлению основан на предложенном Дж. Ферранте, К. Оттенштейном и Дж. Уорреном ее формальном определении. Пусть G = ((', Е, s, f) — управляющий граф с входной вершиной л и выходной верши- ной I. Не ограничивая общности, будем считать, что каждая вершина имеет не более двух исходящих дуг. Дугам, выходящим из одной вершины, как обычно, будем со- поставлять атрибуты Т (истина) и F (ложь). Напомним, что вершина v постдоминируется вершиной w (w v) в G (или, что то же самое, вершина w— обязательный преемник вершины v), если каждый путь из v в t содержит w. В этом определении начальная вершина пути исключается. В частности, вершина не постдоминирует саму себя. Нетрудно увидеть, что понятие постдоминирования сов- падает с понятием доминирования (непосредственного предшествования) в графе, получаемом из исходного заменой ориентации всех дуг на обратную. Вершина у зависит по управлению от х, если: П существует путь Р из х в у, в котором любая вершина z (за исключением х и у) постдоминируется вершиной у; П вершинах не постдоминируется вершиной у. Если у зависит по управлению отх, то вершина х должна иметь, по крайней мере, две исходящие дуги, т. е. быть распознавателем. Причем, среди дуг есть одна такая, что если после исполнения х осуществляется переход по этой дуге, то у всегда в даль- нейшем исполнится, а если по другой, то у может не быть исполненным. Условие 1 всегда выполняется, если путь Р состоит из одной дуги. Условие 2 всегда выполняет- ся, еслих и у— одна и та же вершина. Это показывает, что данное определение пра- вильно описывает циклы. Подобно зависимостям по данным, зависимости по управлению могут быть пред- ставлены ориентированным графом, вершинами которого служат операторы, а дуги указывают на наличие зависимости по управлению. В применении к циклу в управ- ляющем графе данное определение зависимости по управлению характеризует сильно связную область (ССО) зависимости по управлению, вершинами которой являются предикаты, определяющие выход из цикла. Другие вершины цикла управляющего графа, не принадлежащие ССО, лежат на некотором пути, состоящем из дуг зависи- мостей по управлению и выходящем из некоторой вершины ССО. Суммирование вспомогательной информации о зависимости по управлению произво- дится либо с помощью введения в рассмотрение специальных вершин, либо посред- ством системы меток на дугах. Первый способ применяется при построении подграфа зависимостей по управлению графа программных зависимостей Дж. Ферранте, К. Оттенштейна и Дж. Уоррена, второй — при построении иерархического графа за-
860 Часть II. Применение графов и граф-моделей даний, идеографа и некоторых других теоретико-графовых промежуточных пред- ставлений программ. 11.2.4. Граф программных зависимостей Граф программных зависимостей (ГПЗ) представляет собой пару (Gt/, Gc), состоящую из графа зависимостей по данным Gd (в том смысле, как он определен в разд. 11.2.2) и графа зависимостей по управлению Gc. Основой ГПЗ является последний граф, по- этому, говоря о ГПЗ, мы будем иметь в виду именно граф зависимостей по управле- нию. Само понятие зависимости по управлению дано в разд. 11.2.3. Суть ГПЗ состоит в разбиении программы на так называемые регионы — подграфы уграфа, порожден- ные теми вершинами, условия выполнения которых (т. е. соответствующих операто- ров) одни и те же. В определенном смысле регионы представляют собой обобщения линейных участков. Для суммирования множества зависимостей по управлению при формировании регионов в граф вводятся дополнительные вершины (R-вершины) в качестве единственной входной вершины в регион. Все вершины, попавшие в один регион, исполняются в порядке, определяемом наличием между ними зависимостей по данным, и передача управления в другой регион осуществляется только после то- го, как будут исполнены все вершины данного региона. Рис. 11.22. Управляющий граф Рис. 11.23. Граф зависимости по управлению для уграфа На рис. 11.22 и 11.23 представлены управляющий граф и соответствующий ему граф зависимостей по управлению. Вершины START и STOP не входят в граф зависи- мостей по управлению, т. к. они представляют собой пустые блоки, которые добав- ляются к управляющему графу только для удобства анализа. Региональные вершины R1—R6, а также вершина ENTRY введены с целью компоновки множества зависи-
Гпава 11. Преобразование программ 861 мостей по управлению. Вершина ENTRY как бы выражает комплекс внешних усло- вий, приведших к необходимости исполнить программу. Заметим, что от этого ком- плекса условий зависят вершины 1 и 7, поэтому они могут исполняться параллельно, если между ними нет зависимости по данным. Из управляющего графа это не оче- видно. Граф зависимостей по управлению для DO-цикла показан на рис. 11.24. Из него вид- но, что присваивание значений переменной А(1 + 1) входит в сильно связную область и поэтому не может быть распараллелено (векторизовано). Присваивание значения переменной С(/), напротив, можно векторизовать с помощью оператора WHERE, сле- дующего за циклом, определяющим массив А. DO 100 1=1,100 А(1+1)=В(1)+10 IF(A(I)) GOTO 101 C(I)=D(I) 100 CONTINUE 101 CONTINUE Рис. 11.24. Граф зависимости по управлению для цикла 11.2.5. Построение графа зависимостей Первым шагом определения зависимостей по управлению является построение пост- доминаторного дерева для расширенного управляющего графа, кодирующего отно- шение обязательной преемственности между его вершинами. Это расширение состо- ит в добавлении особой предикатной вершины ENTRY, из которой одна дуга, поме- ченная меткой Т, идет в вершину START, а другая дуга, помеченная меткой F, идет в STOP. Вычисление постдоминаторов в уграфе эквивалентно вычислению доми- наторов в обратном уграфе. При использовании алгоритма Ленгауэра — Тарьяна (см. разд. 10.3.3) трудоемкость этого шага составит О(иа(и)), где и— число вершин (ли- нейных участков) в уграфе, а а(л) — медленно растущая функция, обратная функции Аккермана. На рис. 11.25 показано постдом и натор ное дерево для расширенного уграфа, пред- ставленного на рис. 11.22. Следующий шаг состоит в нахождении собственно зависимостей по управлению. Обозначим через S множество всех дуг (v, w) в уграфе, для которых w не является предком v в постдоминаторном дереве (т. е. w не постдоминирует v). Каждая из этих дуг имеет метку Т или F.
862 Часть II. Применение графов и граф-моделей Рис. 11.25. Постдоминаторное дерево В нашем примере имеем S = {(ENTRY, START), (1,2), (1,3), (2,4), (2,5), (3,5)}. Каждая дуга из S просматривается, и для нее отыскивается наименьший общий пре- док L вершин v и и; По построению L не может быть равен w. А. Вершина L в постдоминаторном дереве либо совпадает с V, либо является пред- ком V. В соответствии с этим свойством возможны два случая. □ L — предок v. Все вершины в постдоминаторном дереве на пути из L в w, включая w, но исключая L, зависят по управлению от v. О L = v. Все вершины в постдоминаторном дереве на пути из v в w, включая v и w, зависят по управлению от v. (Этот случай охватывает циклическую зависимость.) Пусть рассматривается дуга (v, w). Так как по свойствам постдом инаторного дерева вершина w расположена не ближе от корня, чем v, будем двигаться от w по направле- нию к корню до предка вершины v (если он существует), помечая при этом все вер- шины, которые встретятся до предка v, как зависимые от v. Этот метод покрывает оба указанных случая, поскольку в первом случае v не лежит на пути в £ и, следователь- но, не помечается. Шаг заканчивается, когда будут проверены все дуги в S. Для нашего примера все зависимости по управлению, которые будут найдены в ре- зультате проверки каждой дуги из множества S, приведены в табл. 11.2. Поскольку в рассматриваемом графе нет контуров, все зависимости соответствуют случаю I. Таблица 11.2. Зависимости по управлению Дуги из S Помеченные вершины Зависимость по управлению от Метка (ENTRY, START) START, 1,7 ENTRY Т (1,2) 2,6 1 Т (1,3) 3 1 F
Гпава 11. Преобразование программ 863 Таблица 11.2 (окончание) Дуги из S Помеченные вершины Зависимость по управлению от Метка (2,4) 4 2 Т (2,5) 5 2 F (3,5) 5,6 3 Т Трудоемкость этого шага — О(и~). Следующий шаг'построения графа зависимости по управлению состоит в добавлении 7?-вершин для формирования множества условий управления для каждой вершины и группировки всех вершин с одним и тем же множеством условий управления. Если при этом одно множество зависимостей по управлению содержит другое, то внутрен- нее множество входит в представление зависимостей по управлению для внешнего множества. /?-вершины вставляются так, чтобы предикатные вершины имели только двух потомков, как и в управляющем графе, и чтобы иерархически организовать за- висимости по управлению. Добавление /?-вершин можно рассматривать как ограни- ченную форму удаления общих подвыражений для зависимостей по управлению и как расширенную форму построения линейных участков. /?-вершины создаются для общих подмножеств зависимостей по управлению, которые выделяются из множест- ва зависимостей по управлению для отдельных вершин. Будем говорить, что две вершины имеют одних и тех же предков относительно зависимостей по управлению, если в каждую из них ведут дуги зависимостей по управлению из одних и тех же вершин, причем соответствующие дуги имеют одинаковые метки Т или F или обе не помечены. Эффективное вычисление множеств зависимостей по управлению и их факторизация основаны на том, что по построению любые вершины, имеющие естественным обра- зом вложенные множества зависимостей по управлению, должны быть смежными на некотором пути в постдоминаторном дереве. Мы вставляем /?-вершины, проходя постдоминаторное дерево в обратном порядке, чтобы все потомки в этом дереве бы- ли пройдены раньше, чем их предки. Вводимые /J-вершины помещаются в хэш- таблицу и, проходя очередную вершину N, подвергаются проверке, нет ли в таблице /?-вершины с тем же множеством CD зависимостей по управлению. Если такой вер- шины нет, то создается новая /^-вершина с множеством предков CD и помещается в хэш-таблицу. Эта /?-вершина R' становится единственным предком вершины У отно- сительно зависимостей по управлению. Затем находится пересечение /NT множества CD с множеством зависимостей по управлению для каждого непосредственного по- томка вершины N в постдоминаторном дереве. Это занимает время О(п). Если пере- сечение INT равно CD, то соответствующие зависимости для потомка заменяются единственной зависимостью от R'. Если для потомка каждая зависимость по управле- нию лежит в пересечении /NT, то для R' соответствующие зависимости заменяются единственной зависимостью от предка этого потомка. Увеличение размера графа в результате включения /?-вершины не приводит к увели- чению времени выполнения этой операции, т. к. такое включение не увеличивает
864 Часть II. Применение графов и граф-моделей размер рабочего списка оставшихся вершин при обратном прохождении постдомина- торного дерева. Поскольку каждая вершина в постдоминаторном дереве проверяется дважды (один раз как потомок и один раз как предок), этот шаг имеет в худшем случае трудоем- кость О(л"). Для нашего примера на рис. 11.26 показан частичный граф зависимости по управле- нию после посещения вершин 4, 5 и 2 (приведшего к созданию /?-вершин 7?1, R2, R3) и сразу же после создания Д-вершины R4 для вершины 6. Множество CD для верши- ны 6 имеет вид {37} 17}. Его пересечение с множеством зависимостей по управлению для предка 5 вершины 6 непусто и равно {37}. Пересечение CD с множеством зави- симостей по управлению для предка 2 равно {17} и соответствует ДЗ. Таким образом, посещение вершины 6 завершается удалением дуги (1, R4) с меткой Т и заменой ее непомеченной дугой (ДЗ, Д4). На рис. 11.27 показан граф, который получается после посещения всех вершин. Рис. 11.26. Частичный граф зависимости по управлению Рис. 11.27. Полный граф зависимости по управлению
Гпава 11. Преобразование программ 865 Второй этап включения /?-нершин предусматривает обход графа, чтобы гарантиро- вать, что для каждой предикатной вершины каждому значению предиката соответст- вует единственный потомок. С этой целью для каждой предикатной вершины Р графа зависимостей по управлению, имеющей несколько потомков относительно зависимо- сти по управлению, которым сопоставлена одна и та же метка L, создается новая /J-вершина. Эта 7?-вершина будет единственным предком для всех указанных потом- ков. Она же будет единственным потомком вершины Р с меткой L. Поскольку преди- кат может иметь максимум О(л) потомков, полное время выполнения этого шага со- ставляет О(п~). Для нашего примера на рис. 11.26 из вершины 3 к вершинам R2 и R4 ведут дуги с меткой Т. Для устранения этого вводится новая вершина R6, объединяющая эти зависимости. Окончательный вид графа зависимости по управлению показан на рис. 11.27. Описанный способ построения графа зависимостей по управлению имеет трудоем- кость О(и2). 11.2.6. Иерархический граф заданий Иерархический граф заданий (ИГЗ) представляет собой промежуточное представле- ние распараллеливаемой программы, которое инкапсулирует только необходимые зависимости по управлению и данным и которое может быть использовано для выяв- ления функционального параллелизма, или параллелизма на уровне заданий. Иерар- хическая природа ИГЗ облегчает эффективное управление степенью разбиения в про- цессе генерации кода и, таким образом, обеспечивает применимость для множества параллельных архитектур. При построении ИГЗ на заданном уровне иерархии требу- ется установить условия исполнения заданий, которые максимизируют параллелизм на уровне задания, и оптимизацию этих условий, что приводит к уменьшению издер- жек синхронизации, навязанных зависимостями по управлению и по данным. ИГЗ реализован в компиляторе (среде) Parafrase-2; он используется как промежуточное представление Фортран- и Си-программ для генерации как параллельной версии входной программы, так и параллельного машинного кода. ИГЗ определяется в точности так же, как и управляющий граф (на базе которого и строится ИГЗ), с одним отличием: ИГЗ — бесконтурный орграф с вершинами трех типов: П простая вершина, представляющая задачу, не имеющую подзадач; П составная вершина, представляющая задачу, которая состоит из других задач в форме ИГЗ; П грошовая вершина, представляющая задачу, являющуюся циклом программы, тело которого есть ИГЗ. В ИГЗ используется иерархия циклов, а не иерархия интервалов, т. к. последняя не позволяет идентифицировать интервал как задание (в силу присутствия в интервале бесконтурной части). Сводимые графы (программы) могут быть легко отображены в иерархическую структуру, основанную на циклах (точнее, на зонах или компонентах 28 Зак. 202
866 Часть II. Применение графов и граф-моделей сильной связности), при соблюдении некоторых дополнительных условий. Речь идет о двух случаях, когда контуры в графе (циклы в программе) пересекаются, но ни один из них не вкладывается в другой, и когда контур имеет по крайней мере два выхода. Случай 1. Циклы С( и С2 имеют общую часть, С| п С2 0, но не содержатся один в другом, т. е. ни С( с С2, ни С2 с Q . В этом случае оба цикла могут быть объедине- ны в один общий цикл (рис. 11.28). Рис. 11.28. Объединение циклов с общей частью Случай2. Цикл С имеет несколько выходов (рис. 11.29). Проблема решается соз- данием новой вершины (вершина v на рис. 11.29, б) и дуг, соединяющих выходы цик- ла с новой вершиной (дуги (2, v) и (4, v) на рис. 11.29, б). В общем случае необходимо вводить дополнительные переменные для "запоминания", какой выход куда ведет из новой вершины. Рис. 11.29. Объединение циклов с несколькими выходами: а — исходный цикл с двумя выходами, б — представление исходного цикла На рис. 11.30 приведен пример ИГЗ для простой программы. На верхнем уровне иерархии граф состоит из четырех вершин, из которых вершины А и В суть цикличе-
Глава 11. Преобразование программ 867 ские вершины, a D — составная вершина. Эти вершины соответствуют управляющим графам структур более высокого уровня, таких как циклы и подпрограммы. На сле- дующем уровне иерархии вершина В состоит из трех вершин, одна из которых (С) соответствует циклической структуре. Таким образом, ИГЗ на рис. 11.30 есть трех- уровневый граф; на третьем (нижнем) уровне он состоит из 16 заданий, соответст- вующих линейным участкам. Каждая вершина есть задание с одним входом и одним выходом на ее уровне иерархии. BEGIN ВВ_1 IF С1 THEN DO 1=1 ,N ВВ_2 ENDO ELSE DO 1=1 ,M BB_3 DO J=1.K IF 02 THEN BB_4 ELSE BB_5 ENDIF BB_6 ENDO ENDO ENDIF CALL SUBROUTINE X END SUBROUTINE X IFC3THENBB_7 ELSE BB_8 ENDIF BB_9 Рис. 11.30. Иерархический граф заданий простой программы 11.2.7. Построение ИГЗ Пусть G = (V, Е, s) — управляющий граф, и пусть в G проведен поиск в глубину, на- чиная из вершины s, в результате чего все дуги разбиваются на четыре класса: дре- весные, прямые, поперечные и обратные. Пусть, далее, В есть множество дуг, концы которых доминируют над их началами. Граф G является сводимым, если G' = (V, Е \ В) — бесконтурный граф.
868 Часть II. Применение графов и граф-моделей Имеет место следующее утверждение. А. Для сводимого графа дуга е является обратной дугой тогда и только тогда, ко- гда е е В. Пусть Т(х) — множество потомков (всех!) вершины х в дереве поиска в глубину. Оче- видно, что если j' 6 Т(х),.Т(у) с Т(х). Цикл (программы) Цх, у), соответствующий обратной дуге (х, у), определяется как у плюс множество вершин v таких, что в G существует путь из v в х, для каждой вер- шины z которого справедливо включение z g Т(у). Вершина у при этом называется заголовком (головной вершиной) цикла. Иллюстрацией этого определения служит рис. 11.31. При традиционном определении цикла для сводимого графа вершина v принадлежит циклу ТЦх,у), если либо v = у, либо существует путь Р из v в х, который не содержит у. Для несводимых графов это определение не работает, т. к. вполне возможно суще- ствование пути из вершины вне цикла (скажем, w) в вершину внутри тела цикла, ми- нуя головную вершину; в таком случае мы должны были бы отнести w к циклу TL, что неверно. Рис. 11.31. Пример цикла, соответствующего обратной дуге (10,4) Ц7.4)={4.5,6.7.8.10} Ц8..3)=Ц4.3)= {3,4.5,6,7,8,10} Ц9,1)={111,2,3,4,5,6,7.8,9.10} Т1_(10,7)={7,8,10} ТЦ7.4)={4.5,6,7}
Глава 11. Преобразование программ 869 Б. Если G сводим, то Цх, у) — TL(x, у) для любой обратной дуги (х, у). В. Пусть Ца, Ь) и L(c, d) — два цикла. Если b е L(c, d)ub^d, то L(a, Ь) с £(с, d). Г. Пусть b^duZ= (L(a, b) n L(c, d)) * 0. Тогда либо Z = L(a, b), либо Z = L(c, d). Пусть .S'(x) — множество начальных вершин обратных дуг, заходящих в х. Определим множество 1{х) зон для всех х из H(G), где //(G) = {х : х е V и существует у такое, что (у, х) — обратная дуга}, следующим образом: /(х) = U>e,S(A) £(у,х). Дня графа на рис. 11.31 имеем: /(1) = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, /(3) = {3, 4, 5, 6, 7, 8, 10}, /(4)={4, 5, 6, 7, 8, 10}, 7(7) = {7, 8, 10}. Пусть Ф'(С7) = {/(х) : х е //(G)} О {И} -— множество зон графа G с дополнительным элементом V. Обобщением утверждения Г служит следующее утверждение. Д. Для любых двух элементов А и В из Ф'(С) либо А П В = 0, либо один из элементов целиком содержится в другом. Для любого элемента А е Ф'(О) положим Р(А) = {В:йе Ф'Д ей}. Для графа на рис. 11.31 имеем: /’(/(1)) — {И}, Р(/(3)) = {/(1), И}, /’(/(4)) = = {/(3), /(1), И}, W)) = {/(4), /(3), 7(1), Е}, Р(Ю={}- Если С, D е Р(А), то С о D * 0, и либо С с D, либо D с С. Это определяет линейный порядок на множестве Р(А). Следовательно, если Р(А) * 0, то существует единствен- ный минимальный элемент £„„„(4) в Р(А) такой, что для любого элемента В е Р(А), В * Рт1„(А) имеем ДПЙ,(Л) <= В. Определим на множестве Ф' функциюf: Ф'—> (Ф’о {7VG££}) следующим образом: fNULL, если Р(А) = 0, ДА) = l^nin(^)—в противном случае. Так как А с V для всех А е Ф', Р(А) есть пустое множество и, следовательно, ДА) = NULL только в случае, когда А — V. Пусть Ф = Ф'и V. Для графа на рис. 11.31 имеем: Ф = {/(1), 7(3), /(4), /(7), V, ENTRY, EXIT, 1,2, 3, 4, 5, 6,7, 8, 9, 10}. Расширим область определения функции f до Ф. Если х е V, то положим Р(х) = {В : В е Ф', х е В}. Очевидно, что пересечение любых двух элементов в Р(х) непусто, когда х принадлежит всем этим элементам, и £(х) непусто, когда V е Р(х) для всех х е V. Как. и прежде, можно доказать существование Рт\п(х)', следовательно. Дх) = Pminfx) определена верно. Для удобства определим /°(х) как тождественную функцию и/"(х) как н-кратную композицию функции f Функция f определяет корневое ордерево с корнем V на элементах множес тва Ф (рис. 11.32). В этом ордереве дуга (А, В) существует тогда и только тогда, когда flA) = В. Р(А) в этом случае есть множество собственных потомков А в дереве. Напомним, что ИГЗ (на каждом уровне иерархии) есть бесконтурный орграф. Будем обозначать его HTG = (HV, НЕ).
870 Часть II. Применение графов и граф-моделей NULL Рис. 11.32. Корневое ордерево функции f Вершины ИГЗ могут быть одного из следующих типов: П входная вершина START: у нее нет входящих дуг, и из нее достижима любая дру- гая вершина; П выходная вершина STOP: у нее нет исходящих дуг, и она достижима из всех ос- тальных вершин; П простая вершина: она изображает задание, не имеющее подзаданий; □ составная вершина: она изображает задание, содержащее хотя бы одно подзада- ние. Каждой такой вершине соответствует свой ИГЗ; П цикловая вершина: она изображает цикл как отдельное задание, телу которого, как и в случае составной вершины, соответствует свой ИГЗ. Построение множества вершин ИГЗ Построение основывается на том, что каждый элемент множества Ф = Ф' U V соот- ветствует вершине ИГЗ. Будем обозначать вершину, соответствующую х е Ф, через g(x). Кроме того, для х е Ф' существуют еще входная и выходная вершины. Таким образом, множество вершин ИГЗ на всех уровнях задается следующим соотношени- ем: VHrG = {g(x): л- е Ф} и {START(g(x)): хе Ф') и {STOP(g(x)) : х е Ф'}. Определим тип каждой вершины X е VHtg- П Х= START(g(x)). X имеет тип входная вершина; П Х= STOP(g(x)). X имеет тип выходная вершина; П X— g(x), х е Ф: • х g И X имеет тип простая вершина; • х = К X имеет тип составная вершина; • х = Цу) для некоторого у е HG. X имеет тип цикловая вершина.
Гпава 11. Преобразование программ 871 Единственные вершины в ИГЗ, не являющиеся значениями функции g, — это различ- ные входные и выходные вершины. Аналогично функции /: Ф'—> (Ф'сэ {NULL}) определим функцию F: Унте (Унге {NULL}) следующим образом: □ Х= START(g(x)) F(X) = g(x)-, □ Х= STOP(g(x)). F(X) = g(x); □ X~g(x), x e Ф; . xe V.F{X)= glfix))', • x=P.F(X) = NULL; • x = I(y) для некоторого у g H(G). F(X) = g(fix)). Если положить g(NULL) = NULL, то получим следующее соотношение- F(g(x)) = g(fix)). В этих обозначениях определим множество НУ вершин для каждой конструируемой составной и цикловой вершины X ИГЗ, НУ(Х) g Унте* как НУ(Х) = = {Y:F(Y)=X}. Рассмотрим ИГЗ для вершины g(Z(l)) графа на рис. 11.33. Имеем //K(g(/(1))) = = {У: F(Y) = g(/(l))}, /(1) = {1, 2, 3, 4, 5,6, 7, 8, 9, 10} = {1, 2, 9, 1(3)} и //P(g(/(1))) = = {START, STOP, g(l), g(2), g(l(3)), g(9)}. Рис. 11.33. Иерархический граф заданий Построение множества дуг ИГЗ Каждая дуга (<?, Ь) в управляющем графе G будет порождать новые дуги, добавляе- мые к ИГЗ. Для этого для каждой дуги (о, Ь) совершаются следующие действия. На- зовем /-деревом ордерево, изображающее иерархическую структуру циклов исходно- го графа. Тогда: 1. Найти в /^дереве наименьшего общего предка z вершин fia) и fib) (если fia) = fib), то z =fia)). Пусть z =/"(а) —f\b), и, m> 1 2. Добавить дуги (g(f(a)), STOP{g(f+ \a)))) к HE(g(f \a))) для 0 < i < л-2. 3. Добавить дуги (START(g(fi(b))), g(fi-'(b))) к HE(g(fi(a))) для 1 < i < л-1.
872 Часть II. Применение графов и граф-моделей 4. Если (о, Ь) не является обратной дугой, то добавить к HE(g(z)) дугу (gif' '(«)), 5. Если (a, b)— обратная дуга, то добавить к HE(g(z)) дуги (g(/" '(a)), STOP(g(z))) B(START(g(z)),g(f'-'(b))). К множеству HE(g(f")) также добавляются дуги (START(g(F)), g(ENTER)) и (g(EA77), STOP(g(V))), соответствующие вершинам ENTRY и EXIT управляющего графа. Из этого построения и из соотношения F(g(x)) = g(/(x)) следует, что если в ИГЗ добавля- ется дуга между вершинами А" и У, то F(X) = F(Y) и, кроме того, выполнено выделение обратных дуг в исходном уграфе, то граф HTG(X) = (HV(X), НЕ(Х)) становится бес- контурным для любой составной или цикловой вершины X. Для нашего примера ИГЗ вершины 7(1) показан на рис. 11.32. Вершинами уграфа для g(7(l)) являются START(g(I(i))), STOP(g(I(i))), g(l), g(2), g(9), g(/(3)), т. к. /(1) =/2) = =Л9)=Л/(3)) = /(1). Этим завершается построение уграфа для ИГЗ на каждом уровне иерархии. Следую- щий шаг состоит в построении для каждого уровня графов зависимостей по данным и по управлению в составе ИГЗ. Составные и цикловые вершины Пусть для некоторой составной или цикловой вершины построен управляющий граф CFG - (V, Е). По построению CFG — бесконтурный граф. Несколько изменим данное в разд. 11.2.3 определение зависимости по управлению и будем говорить, что в усло- виях этого определения вершина у зависит от х с меткой х - а, если дуга (х, а) е CFG является первой дугой на пути Р из х в у. Будем называть в этом случае дугу (х, а) ветвью; заметим, что все метки могут быть только ветвями. Граф CDG = (СЕ, СЕ) зависимости по управлению для заданного уграфа CFG = (V, Е) есть орграф с помеченными дугами такой, что □ CV= V; □ (х, у)&СЕ с меткой х — а тогда и только тогда, когда х8су с меткой х — а. Граф CDG строится из уграфа CFG с помощью постдоминаторного дерева. Если (х, у) — произвольная ветвь в CFG, тогда справедливы следующие утверждения. Е. Пусть z — непосредственный предок х в постдоминаторном дереве. Тогда бли- жайший общий предок вершин хиу в постдоминаторном дереве есть либох, либо z. Ж. Все вершины на пути из у в z ( не включая z) в постдоминаторном дереве зависят по управлению от х с меткой х—у. Рассмотрим управляющий уграф CFG на рис. 11.34, его постдом инаторное дерево представлено на рис. 11.35. На рис. 11.36 показан граф CDG для управляющего графа CFG. Итак, ИГЗ представляет собой иерархию управляющих графов, каждый из ко- торых есть бесконтурный граф и для каждого из которых строил ся граф DDG зависи- мостей по данным и граф CDG зависимости по управлению. Возможный граф DDG для CFG показан на рис. 11.37.
Глава 11. Преобразование программ 873 Рис. 11.35. Постдоминаторное дерево уграфа CFG Рис. 11.36. Граф зависимости по управлению для уграфа CFG Рис. 11.37. Граф зависимости по данным для уграфа CFG
874 Часть II. Применение графов и граф-моделей 11.3. Операторные модели программ Во многих задачах, связанных с обработкой программ, удобно иметь дело не с де- тальным описанием программы, а с ее упрощенной моделью — операторной схемой программы, в которой такие понятия, как оператор, операнд, переменная, выполне- ние и т. д., являются обобщением соответствующих понятий существующих языков программирования. Схема программы моделирует целый класс конкретных про- грамм, имеющих одинаковую информационно-логическую структуру, т. е. описывает его таким образом, что множес тво преобразований, корректных для схемы, образует- ся из преобразований, корректных для всех моделируемых ею программ. При пере- ходе от программы к моделирующей ее схеме игнорируются несущественные осо- бенности (например, синтаксические) конкретного языка программирования и сохра- няются только те семантические свойства программы, которые используются при ее анализе и преобразовании. 11.3.1. Семантические и формальные схемы программ Одновременно с появлением первых систем автоматизации программирования воз- никли и стали бурно развиваться два направления в теории операторных схем про- грамм в качестве теоретической основы эквивалентных и оптимизирующих преобра- зований транслируемых программ и их обоснования. Первое направление изучает отношения эквивалентности в разных семантических моделях программ с целью построения полных систем эквивалентных преобразова- ний. Семантическая модель программы — это множество схем с введенным в нем отношением эквивалентности. В семантической схеме конкретные объекты програм- мы (например, переменные, константы и операции) заменяются на формальные сим- волы, а моделируемая программа получается из схемы некоторой интерпретацией формальных символов, входящих в схему. Множество выполнений схемы определя- ется таким образом, что оно покрывает множество выполнений каждой программы с данной схемой, а две схемы объявляются функционально эквивалентными, если функции, вычисляемые схемами, совпадают. Исходной для исследования является функциональная эквивалентность схем, хотя изучаются также и более сильные фор- мы эквивалентности, главным образом для того, чтобы выявить те свойства моделей, без выполнения которых построение полной системы либо невозможно, либо затруд- нено. В рамках этого направления были получены важные результаты по нахождению и исследованию разрешимых случаев эквивалентности и полных систем эквивалентных преобразований. Однако требование разрешимости приводило к тому, что большин- ство преобразований, полезных для оптимизации, находилось вне исследованных моделей программ. Практически же применяемые оптимизирующие преобразования (и другие виды се- мантической обработки программ) изучались в рамках второго направления в теории схем программ, связанного с изучением так называемых "направленных преобразо-
Глава 11. Преобразование программ 875 ваний". Идея, лежащая в основе этого подхода, состоит в формулировании практиче- ски полезного способа оптимизации программ (или другого вида работы с програм- мой) в виде некоторого класса формальных схем, представляющего собой специаль- ную символическую запись реальных программ или их фрагментов с заданной (явно или неявно, с помощью инварианта) системой формально корректных преобразо- ваний. Класс формальных схем может отражать только те из свойств реальных программ, которые наиболее существенны для выбранного способа их обработки, и не обязан охватывать их полностью и во всем классе программ. Таким образом, это направле- ние позволяет изучать достаточно глубокие способы обработки программ, оставаясь в рамках прос тых (разрешимых) моделей. Однако практическое применение получен- ных при этом результатов для создания оптимизирующих трансляторов (и других инструментальных систем) требует решения ряда нетривиальных задач по установле- нию связи между изученными классами формальных схем и классом преобразуемых программ. Наиболее важной из этих задач является задача схематизации программ, при которой формальные схемы корректно и достаточно полно отражают выбранный способ обработки, а переход от программы к ее формальной схеме и обратно имеет приемлемую сложность. В том случае, когда нужно реализовать не один, а несколько способов обработки (что, как правило, и бывает), возникает проблема такого объеди- нения систем формальных преобразований, чтобы совместный эффект их применения оказался наибольшим. Поэтому исследование систем преобразований в рамках фор- мальных схем должно подкрепляться выделением и изучением семантических моде- лей программ, для которых эти преобразования являются корректными. 11.3.2. Класс крупноблочных схем программ Крупноблочная схема рассматривает моделируемую программу в виде совокупности структурных операторов, обрабатывающих структурные значения совокупности пе- ременных. Она может быть представлена в виде текста на некотором языке "поли- программирования", который в отличие от обычного языка программирования до- пускает семантическую многозначность данных и операций. Фиксация одной из воз- можных интерпретаций превращает крупноблочную схему, которая до этого времени является "полипрограммой" (описанием целого множества крупноблочных программ, имеющих одну и ту же структуру), в конкретную программу. В практике программирования широко используется так называемое блок-схемное представление программ, которое содержит в явном виде задание системы управ- ляющих связей между ее операторами. Аналогичная форма представления особенно удобна для операторных схем программ. Классы операторных схем программ, в том числе класс крупноблочных схем, харак- теризуются наборами базисных символов, из которых строятся схемы, и правилами композиции этих символов, определяющих вид выражений и операторов схем. Ба- зис Z, над которым строя гея крупноблочные схемы, содержит символы переменных, операций, доступов, предикатов выполнимости, выбора и операндов: обязательных и необязательных входов и выходов.
876 Часть II. Применение графов и граф-моделей Крупноблочная схема а.— это тройка (Go, Ra, Qa), в которой Ga—управляющий граф (уграф), Ra — раскраска операндов операторов из Ga, сопоставляющая каждому операнду некоторую переменную, a Qa — множество интерпретаций базиса. Переменные, сопоставленные входам операторов, называются их аргументами, а выходам — результатами. Аргументы и результаты разделяются на обязательные и необязательные в зависимости от того, являются ли таковыми операнды, которым они сопоставлены. Каждая интерпретация / е Qa— это совокупность, состоящая из области интерпре- тации D, и двух функций. Одна из них сопоставляет элементам базиса Е элементы £)/ и функции, заданные на D\, а вторая выделяет используемые и неиспользуемые части аргументов интерпретирующих функций при вычислении указанных частей их ре- зультатов. Предполагается, что £>, может содержать как простые значения, так и со- ставные. Каждое из составных значений — это множество упорядоченных пар эле- ментов из Db попарно различающихся по первым компонентам, называемым их име- нами. Таким образом, одно значение может образовывать нетривиальную часть другого значения с некоторым адресом, представляющим собой последовательность имен. Оператор (в общем случае) — это совокупность, состоящая из слова применимо- сти— выражения, описывающего условия применимости оператора и построенного из обязательных входов и операций, слова выбора— выражения, построенного из входов и операций и описывающего правила выбора той из исходящих дуг, по кото- рой будет осуществлен переход, а также из множества обязательных и необязатель- ных присваиваний, описывающих правила перевычисления состояния памяти. Обязательное присваивание имеет вид а := F, где а — получатель (обязательный вы- ход), a F— источник, представляющий собой выражение, пос троенное из входов и операций и описывающее правило вычисления значения, которое будет присвоено переменной R(a). Необязательное присваивание имеет вид g(Fb ..., F,, F, а), где g— символ доступа, а— получатель (необязательный выход), F— источник, F\,..., Fr— ключи, представ- ляющие собой выражения, построенные из входов и операций. В зависимости от ин- терпретации g и текущих значений ключей определены используемые и неиспользуе- мые части как переменной х = R(a), так и текущего значения источника F. Необяза- тельное присваивание сохраняет значения используемой части х и перевычисляет неиспользуемую часть х, размещая в ней используемые части значения источника. На множестве операндов оператора определены два отношения: отношение эквива- лентности, задающее множество (информационно) связных операндов, и симметрич- ное отношение (информационной) несовместимости. Предполагается, что любые два операнда не являются одновременно связными и несовместимыми, а все выходы од- ного и того же оператора попарно несовместимы При этом раскраска должна сопос- тавлять любым двум связным операндам одну и ту же переменную, а любым двум несовместимым — разные. С каждой интерпретацией I е Qa связывается выполнение схемы а. Это выполнение состоит из конечной или бесконечной последовательности шагов, на каждом из кото-
Глава 11. Преобразование программ 877 рых происходит выполнение определенного оператора схемы при определенном те- кущем состоянии памяти — функции W, сопоставляющей каждой переменной х е X элемент И^х) е Df, называемый значением х при состоянии памяти W. Выполнение оператора в общем случае приводит к завершению (аварийному или нормальному) выполнения всей схемы либо к изменению текущего состояния памяти и выбору сле- дующего оператора для выполнения. Правила выполнения схемы а при I таковы, что операторы схемы выбираются для выполнения в порядке их вхождения в некоторый путь по уграфу (5о = старт, щ, St, и2, S2,..., S„ ...), называемый цепочкой выполнения а. при /. Выполнения операторов порождают последовательность текущих состояний памяти (fVh И'2,..., И),...), в кото- рой IV t — начальное состояние памяти, сопоставляющее каждой переменной х е X элемент JT^x) = /(х), а каждое W, +1 получается как результат выполнения оператора S, при состоянии памяти W,. Оператор останова стоп осуществляет нормальное завершение выполнения схемы а при интерпретации / и фиксирует в качестве его результата va/(a, Г) упорядоченный набор значений (di,dr), где d, — значение /-го входа оператора стоп при текущем состоянии памяти. Выполнение оператора S, не являющегося начальным или конечным, состоит из вы- полнения составляющих его логического выражения, присваиваний и переключателя. В ходе их выполнения происходит обращение к значениям (копирование во внутрен- нюю память оператора) определенных частей переменных-аргументов, а также выра- ботка новых значений и замещение ими текущих значений переменных-результатов или их определеннных частей. При этом в случае ложности логического выражения выполнение оператора S аварийно завершает выполнение всей схемы. Интерпретация / называется результативной, если выполнение ос при I нормально завершается, и нерезультативной — в противном случае, т. е. если выполнение а при I завершается аварийно либо не завершается (т. е. состоит из бесконечного числа ша- гов). Для нерезультативной интерпретации / значение val(a, Г) не определено. В процессе выполнения схемы между выходами и входами операторов могут реали- зовываться информационные связи. Говорят, что в ходе выполнения а при I между выходом а оператора S, и входом оператора S, реализуется информационная связь по передаче значения d через переменную х. если S, по входу b читает из части перемен- ной х значение d, присвоенное ей через выход а в результате выполнения операто- ра S,. Будем предполагать, что у оператора старт имеется множество фиктивных обяза- тельных выходов, содержащее по одному выходу для каждой переменной, сопостав- ленной этому выходу раскраской в любой схеме. Таким образом, если схема не опи- сывает программу целиком, в схеме возможны информационные связи между выхо- дами оператора старт и входами других операторов. Схема а вычисляет схему р, если ОрсПа, и любая интерпретация I е Qp, являю- щаяся результативной для схемы р, является также результативной для а, причем val(a, Г) = val($, Г). Схемы аир (функционально) эквивалентны, если они вычисляют
878 Часть II. Применение графов и граф-моделей друг друга. Схема ос тотальна (соответственно пуста), если все ее интерпретации результативны (соответственно нерезультативны). Путь по ос от его начального оператора называется допустимым, если существует такая интерпретация I е что он является префиксом выполнения ос при I. Схема ос свободна, если каждый путь по ос от ее начального оператора является допустимым. В качестве примера рассмотрим схему ос на рис. 11.38. Здесь, как и обычно, вершины уграфа изображаются прямоугольниками, а дуги, исходящие из одного оператора, расположены слева направо в соответствии с их упорядоченностью. Выступы на опе- раторах — это их операнды (сверху входы, а снизу выходы); обязательные входы и выходы черные. Буквы, указанные рядом с операндами,— это сопоставленные им переменные. Предполагается, что входы и выходы каждого оператора занумерованы слева направо и упоминаются своими номерами в изображении оператора. Внутри прямоугольника слова оператора выписываются столбиком: сначала логическое вы- ражение, если оно есть, затем все присваивания и, наконец, переключатель, если опе- ратор является распознавателем. В данном примере Qa состоит из всех таких /, для которых О/— это множество целых чисел, и для любых к и г из D, справедливы сле- дующие свойства для функций 1(f) и /(Г,), интерпретирующих /и Г(: I(f)(k, г) = к- г; I(f\)(k, г) = 1, если к - г; 1(Г2)(к, г) = 1, если к<г. Таким образом, схема ос описывает программу вычисления наибольшего общего делителя двух целых чисел. Эта же про- грамма описывается схемами Р и у (рис. 11.38), в которых для любой I g Qp о Qy интерпретации символов f Г], Г2 сохраняются, а интерпретации функций доступа следующие: □ к, s) равно s, если i < j, и равно к иначе; П I(h)(i,j, к, s) равно я, если i — делитель для j, и равно к в противном случае; Рис. 11.38. Примеры крупноблочных схем
Глава 11. Преобразование программ 879 П равно наибольшему общему делителю чисел I и j, если / > 0 и j > 0, и равно нулю в противном случае. Фундаментальную роль при использовании схем программ играют не только отноше- ния эквивалентности и вычисляемости между схемами, но и отношение моделиро- вания Обычно мы имеем дело по крайней мере с двумя схемами, описывающими исходную (обрабатываемую) программу: одна схема (обозначим ее через а)— эта сама исход- ная программа, ставшая схемой в силу отсутствия полной информации о программе, а другая схема (обозначим ее через Р) — это схемное представление исходной про- граммы, в терминах которой формулируется наша обработка. Работа со схемой а в терминах р корректна, если р моделирует а, т. е. схема Р описывает весь класс программ, который описывается схемой а, и делает это согласованно с ней (вся ин- формация, извлекаемая из р при ее анализе, является достоверной по отношению к а, а все преобразования, корректные по отношению к схеме р, соответствуют коррект- ным преобразованиям схемы а). Часто требуется, чтобы один оператор (или одна переменная) схемы р моделировал целый фрагмент (соответственно группу перемен- ных) схемы а. Это связано с тем, что большинство реально используемых видов об- работки задается не по отношению к отдельным командам или ячейкам машинной программы. Многоуровневого и разномасштабного схемного представления требует и такой широко используемый прием реализации глобального преобразования с при- емлемыми затратами, как факторизация. Понятие моделирования одной крупноблочной схемы другой уточняется следующим образом. Пусть имеется некоторая схема а. Масштаб (укрупнение) схемы а — это пара А = (Дь А2), состоящая из разбиения А, множества операторов схемы а на фраг- менты и разбиения А2 множества переменных схемы а на области памяти; он тривиа- лен, если А, и Д2 содержат только тривиальные элементы. Схема Р моделирут схему а с масштабом А, если существуют соответствия между переменными и операторами моделирующей схемы р и фрагментами А, и областями памяти А2 моделируемой схемы а, в рамках которых для любого выполнения схемы а найдется информацион- но и логически совпадающее с ним выполнение схемы р. А. Существует алгоритм, который по любой схеме а и по любому ее масштабу д. строит схему Р, моделирующую а с масштабом А. В практике оптимизации (и других видов обработки программ) представляется весь- ма важной точность моделирования одной схемы другой, однако справедливо сле- дующее свойство. Б. Проблема точного моделирования в классе крупноблочных схем является нераз- решимой. Крупноблочная модель программ вместе с концепцией крупноблочного моделирова- ния одних схем другими дает единую позицию для комплексного исследования экви- валентных и оптимизирующих преобразований программ со структурами данных и действий. Существенными свойствами, отличающими класс крупноблочных схем от других операторных моделей программ, являются его универсальность в смысле ши-
880 Часть II. Применение графов и граф-моделей роты описания класса последовательных программ и способов их оптимизации, а также его полнота— возможность построения по любой крупноблочной схеме (в частности, программе) и любому ее укрупнению такой другой крупноблочной схе- мы, которая моделирует исходную при заданном ее укрупнении. 11.3.3. Важные подклассы и их свойства Рассмагриваются разные подклассы крупноблочных схем, ориентированные на ре- шение определенных способов обработки программ. Эти подклассы характеризуются своими ограничениями на набор базисных символов, на вид выражений и операторов схемы, а также на множество интерпретаций. Неинтерпретированные схемы Данные схемы представляют собой важный подкласс крупноблочных схем, состоя- щий из всех тех схем, в которых множество интерпретаций совпадает с множеством всех возможных интерпретаций базиса. Этот подкласс содержит схемы Мартынюка и стандартные схемы и ориентирован на чисто схемные преобразования программ, ко- торые предполагают доступность только информационно-логической структуры про- грамм и составляют ядро различных видов обработки программ. При исследовании ряда свойств неинтерпретированных схем, таких как корректность того или иного преобразования, можно ограничиваться рассмотрением так называе- мых свободных (или эрбрановых) интерпретаций базиса, составляющих небольшую и вполне обозримую часть всех интерпретаций. Основу этих интерпретаций составляют термы значений — слова, правильно построенные из констант, переменных и симво- лов операций и доступов. Пусть а = (Ga, Ra, Q) и р = (Gp, Rp, Q) — две неинтерпретированные схемы, а а и Р — схемы (Ga, Ra, Q) и (Gp, Rp, Q ), получаемые из a и p заменой Q на множество £7 всех свободных интерпретаций. А. Схема а вычисляет схему Р (соответственно эквивалентна схеме р) тогда и только тогда, когда а вычисляет (соответственно эквивалентна Р ). Б. Схема а свободна (соответственно пуста или тотальна) тогда и только тогда, когда схема а свободна (соответственно пуста или тотальна). Схемы Мартынюка Неинтерпретированные схемы (рис. 11.39), в которых не содержится никакой инфор- мации о программе, кроме членения программы на операторы с указанием совпа- дающих (эквивалентно работающих) операторов и системы управляющих связей ме- жду операторами, получили название схем Мартынюка. Схема Мартынюка как крупноблочная схема включает только одну переменную и состоит из операторов, каждый из которых имеет два операнда: обязательный вход и необязательный выход. Для схемы Мартынюка естественным образом определяется множество цепочек— путей по схеме от начальной вершины до конечных. При этом
Глава 11. Преобразование программ 881 две схемы Мартынюка являются функционально эквивалентными, если указанные множества цепочек в них совпадают. Поэтому проблема распознавания функцио- нальной эквивалентности для схем Мартынюка разрешима. Схемы Мартынюка — основная модель программы при решении задач анализа пото- ка управления в программе. Рис. 11.39. Пример схемы Мартынюка Стандартные схемы Стандартные схемы — это схемы алголоподобных программ (рис. 11.40), исследова- ние которых составляет основное содержание общей теории схем программ. В отли- чие от схем Мартынюка стандартные схемы учитывают разбиение памяти на пере- менные и позволяют исследовать более широкий класс преобразований программ, включающий уже и такие преобразования, как, например, экономия общих подвыра- жений. Однако как подкласс крупноблочных схем стандарные схемы запрещают структурность операторов и переменных и, таким образом, моделируют лишь узкий класс реальных программ. Каждый оператор в стандартной схеме является либо преобразователем — операто- ром, изменяющим состояние памяти, либо распознавателем — оператором, осущест- вляющим выбор для исполнения одного из нескольких своих преемников. Преобра- зователь содержит одно обязательное присваивание и имеет одну исходящую дугу, а распознаватель не содержит присваиваний и имеет две исходящие дуги, одна из кото- рых называется плюс-стрелкой (или \-дугой), а вторая— минус-стрелкой (или 0-дугой). В. Проблемы пустоты, функциональной эквивалентности и свободы стандартных схем не являются частично разрешимыми. Г. Проблема тотальности стандартных схем частично разрешима. Некоторое отношение эквивалентности а называется нетривиальным в классе стан- дартных схем, если выполняются следующие два свойства: □ из неэквивалентности схем cq и «г следует, что существует интерпретация I такая, что va/(ab I) val(a2,1) или одна из схем нормально завершается, а вторая нет;
882 Часть II. Применение графов и граф-моделей □ для того чтобы схемы <Xi и а2 были неэквивалентными, достаточно существования такого оператора, который бы входил в цепочку схемы cq, порождаемую некото- рой интерпретацией /, но не входил в цепочку схемы сс2, порождаемую той же ин- терпретацией I, или наоборот. Д. Любое нетривиальное интерпретационное отношение эквивалентности в классе стандартных схем не является разрешимым. Е. Существует такая стандартная схема а и такой ее масштаб А = (А|, А2), что А2 состоит только из тривиальных областей и любая схема Р, моделирующая схему а с масштабом А, не является стандартной. Схемы Янова Схемы Янова использовались для разработки общей теории условий, управляющих последовательностью выполнений операторов в программе. В отличие от схем Мар- тынюка схема Янова содержит помимо одной переменной (скажем, х), имеющейся в схеме Мартынюка, множество специальных логических переменных р2, ...,рк, управляющих вычислениями. Схема Янова состоит из операторов двух типов: преобразователей и распознавателей (рис. 11.41). Каждый преобразователь, помимо обязательного аргумента и необяза- тельного результата х, имеет произвольное подмножество логических переменных в качестве результатов. Множество логических переменных, являющихся результатами оператора-преобразователя, называется его сдвигом. Каждый распознаватель имеет равно две исходящие дуги и состоит из слова выбора, имеющего вид произвольной логической функции от переменных Р\,р2, -,Рк- Дуги, исходящие из распознавателя, различаются и называются соответственно плюс-стрелкой и минус-стрелкой.
Глава 11. Преобразование программ 883 Минус-стрелка Входная стрелка (помечает входной оператор) Р&П ч A-dP.q) P&q Останов Преобразователь с результатом р Оператор с пустым сдвигом Рис. 11.41. Схема Янова Распознаватель с условием p&lq Плюс-стрелка В классе схем Янова естественным образом выделяется подкласс схем, состоящий из схем определенного стандартизованного (так называемого канонического) вида. Он играет особую роль в исследовании всего класса схем Янова, поскольку любая кано- ническая схема Янова является свободной, а любые две канонические схемы Янова эквивалентны тогда и только тогда, когда они равны. В то же время любая схема Янова может быть преобразована в эквивалентную каноническую схему. В результате процедура распознавания главных свойств схем Янова может быть следующей: по заданным схемам строятся эквивалентные канонические схемы, для которых обнару- жение главных свойств является достаточно тривиальной задачей. Ж. Проблемы свободы, пустоты и тотальности разрешимы для схем Янова. 3. Проблема эквивалентности разрешима в классе схем Янова. Для схем Янова не просто разрешима проблема эквивалентности, но и построена полная система эквивалентных преобразований— система преобразований, сохра- няющих эквивалентность, полная в том смысле, что любую пару эквивалентных схем можно трансформировать друг в друга последовательным применением этих преоб- разований. 11.3.4. Перераспределение памяти Необходимость перераспределения памяти в программах возникает не только тогда, когда требуется экономить память. Неудачное распределение памяти в программе может закрывать возможности применения к ней многих преобразований, которые могли бы применяться, если, например, в программе перейти к так называемому ка- ноническому распределению памяти, максимальным образом распределяющему по памяти операнды операторов программы.
884 Часть II. Применение графов и граф-моделей Перераспределение памяти в крупноблочной схеме а состоит в изменении ее рас- краски — переходе к такой схеме 0, что Ga = Gp и Qa = Qp. А. Проблема распознавания сохранения функциональной эквивалентности при пере- распределении памяти в классе крупноблочных схем является неразрешимой Можно рассмотреть класс перераспределений памяти, при которых для любой интер- претации совпадают множества информационных связей в исходной и результирую- щей схемах. Очевидно, что любое перераспределение, принадлежащее этому классу, является функционально эквивалентным, но обратное не верно: этот класс не содер- жит все функционально эквивалентные перераспределения памяти. Б. Проблема распознавания сохранения перераспределением памяти информацион- ных связей по передаче значений между операндами операторов схемы в классе крупноблочных схем неразрешима. Опишем информационную эквивалентность схем, которая выделяет класс перерас- пределений, обеспечивающих сохранение всех маршрутов информационных свя- зей — тех путей, вдоль которых могут реализовываться эти связи. Эта эквивалент- ность в отличие от функциональной является формальной, т. е. не опирается на поня- тие интерпретации. Информационная эквивалентность является корректной (см. свойство 11.3.4, В) и описывает достаточно широкий класс эквивалентных пере- распределений памяти. Поэтому она широко используется при оптимизации. Путь Р - (5„ S2,..., S,) по схеме а называется маршрутом информационной связи между выходом а оператора S, и входом b оператора S„ если Ra(a) = Ra(b), и внут- ренние операторы пути Р не имеют обязательного выхода d, для которого Ra(d) = = Ra(b). Говорят, что Р реализует (подтверждает) имеющуюся в схеме а информа- ционную связь между а и b по переменной х = Ra(a) = Ra(b). Переменная х называется занятой (живой) перед оператором S (соответственно после оператора S), если существует маршрут информационной связи по х, для которого S— конечный или внутренний (соответственно начальный или внутренний) оператор, и свободной (мертвой), если такого маршрута нет. Схемы а и 0 называются информационно эквивалентными, если Ga = Gp и Ja = Jp, где для любой схемы у через ф обозначается ее информационный граф — такой ориенти- рованный граф, вершинами которого являются операнды, а пара операндов а и b об- разует дугу (а, Ь) графа тогда и только тогда, когда в схеме у существует маршрут информационной связи между выходом а и входом Ь. В. Информационно эквивалентные крупноблочные схемы являются функционально эквивалентными. Говорят, что операнды с и d (информационно) достижимы друг из друга в а, если они информационно связны (образуют дугу в графе Ja) или существует такой третий операнд, из которого оба операнда информационно достижимы. Г. Отношение достижимости является отношением эквивалентности, которое разбивает множество операндов схемы а на классы, внутри любого из которых раскраска Ra сопоставляет операндам одну и ту же переменную.
Глава 11. Преобразование программ 885 Д. Схемы а и р, в которых Ga = G^u Cla = Qp, являются информационно эквивалент- ными тогда и только тогда, когда в этих схемах совпадают отношения информа- ционной достижимости. Пусть задана схема а. Обозначим через Оа — множество всех ее операндов, а через о'а,..., Оц— элементы разбиения Оа на максимальные множества взаимно достижи- мых операндов. Преобразование расклейки состоит в том, что для некоторого множества О(, и пере- менной х таких, что х не является переменной схемы а и Оане содержит фиктивных операндов (т. е. выходов оператора старт), изменяется раскраска Ra таким образом, что R,,(a) = х для любого a g О'а. Две переменные называются несовместимыми, если они сопоставлены двум несо- вместимым операндам или одна из них является результатом такого оператора, после которого занята вторая, и совместимыми — в противном случае. Преобразование склейки состоит в том, что для двух совместимых переменных х и у таких, что нет фиктивного выхода, которому сопоставлена переменная х и из которо- го достижим нефиктивный операнд, изменяется раскраска Ra таким образом, что для любого операнда d, для которого Ru(d) - х, Ra(d) полагается равным у. Е. Две схемы являются информационно эквивалентными тогда и только тогда, ко- гда одна схема может быть получена из другой последовательностью склеек и рас- клеек. Каноническим распределением памяти для схемы а называется распределение памяти R... схемы у, которая информационно эквивалентна схеме айв которой 7?у(а) * Ry(b) для любых двух операндов а и Ь, не являющихся взаимно достижимыми. Сопоставим схеме а неориентированный граф, называемый графом несовместимо- сти. Вершинами этого графа являются множества, О'а..., Ога, а две вершины О'аи (Уа соединены ребром тогда и только тогда, когда нельзя склеить переменные, сопостав- ленные операндам О'аи (9^ при каноническом распределении памяти. Раскраской неориентированного графа называется такое распределение его вершин на группы (окрашиваемые одной краской), при котором не попадают в одну группу никакие две вершины, соединенные ребром. В качестве красок графа несовместимо- сти будем рассматривать символы переменных и считать раскраску допустимой, если любая вершина О'а, содержащая некоторый фиктивный операнд d, окрашена пере- менной Ra(d). Ж. Любая допустимая раскраска графа несовместимости задает схему, информа- ционно эквивалентную исходной схеме. Наоборот, каждая схема, информационно эквивалентная исходной схеме, задает допустимую раскраску ее графа несовмес- тимости. 11.3.5. Схемы с распределенной памятью Имеется два основных способа идентификации взаимовлияний операторов и пере- менных в схеме программ — так называемые общая память и распределенная память.
886 Часть II. Применение графов и граф-моделей В схемах над общей памятью, называемых также О-схемами, такой способ описан в определении крупноблочной схемы — переменные однозначно сопоставляются рас- краской операндам операторов, и любой оператор схемы, засылая значение в пере- менную, не "интересуется", где это значение будет использовано, а используя значе- ние, не "интересуется", какой из операторов это значение выработал. В отличие от общей памяти, где элементы памяти равнодоступны как входам, так и выходам операторов, при распределенной памяти переменные сопоставляются вхо- дам операторов взаимно однозначно, а значение, выработанное на выходе оператора, засылается уже не в одну переменную, а копируется и рассылается в несколько пере- менных. В схемах над распределенной памятью, называемых также P-схемами, вме- сто раскраски используется информационный граф, вершинами которого являются операнды операторов, а дуги отражают пересылку значений от выходов к входам. Таким образом, при распределенной памяти оператор, вырабатывая результат, знает, для каких операторов он предназначен, а воспринимая результат, знает, какой опера- тор его подготовил. Оба способа присутствуют в современных языках программиро- вания и используются в промежуточных представлениях программ. Наиболее извест- ным промежуточным представлением программ с распределенной памятью является SSN-форма. Предполагаем, что О-схема а описывает программу целиком, т. е. при любой интер- претации I е Q„ не существует информационной связи, исходящей из фиктивных выходов оператора старт. Это позволяет удалить из области определения / множест- ва переменных и тем самым дает возможность естественным образом сформулиро- вать эквивалентность О-схем и P-схем, в которых переменные отсутствуют. Схемой над распределенной памятью (или P-схемой) а называется тройка (Ga, Ja, Qa), в которой Ga — управляющий граф, Qa — множество интерпретаций, приписывающих смысл символам функций и константам, а Ja— информационный граф. Вершинами графа Ja являются операнды операторов из Ga, а дуги соединяют выходы операторов с входами таким образом, что для любых операндов а, с и d вы- полняются следующие свойства: если аис — несовместимые выходы и (a, d) — дуга графа Ja, то в Ja нет дуги (с, d); если а и с — связные входы и (с/, а) — дуга графа ./а, то (d, с) является дугой в Ja. Неинтерпретированная P-схема ос приведена на рис. 11.42. Здесь, как и обычно, дуги информационного графа изображены штриховыми стрелками. Рассмотрим цепочку выполнения (старт, Si, S2, S3, S4, стоп). Оператор S, поместит на вход оператора S2 значение сц а на вход оператора стоп — значение с2. Выполнение оператора S2 заме- нит значение, хранящееся на входе оператора стоп, на значение Дс|). Это значение и будет результатом данного выполнения всей схемы а. В отличие от О-схем в /'-схемах элементами памяти являются не переменные, а вхо- ды операторов. Поэтому состояние памяти в P-схеме а сопоставляет текущие значе- ния входам операторов, а всякий оператор S при своем выполнении берет текущие значения со своих входов и может изменить текущие значения только у тех видов Ь, для которых (а, Ь)— дуга графа Ja, где а— выход оператора S. При этом если а-
Глава 11. Преобразование программ 887 обязательный выход, то вход b в качестве нового текущего значения получает значе- ние, выработанное оператором 5 по выходу а; если же a— необязательный выход, то вычисленное оператором S по выходу а значение используется лишь для модифика- ции текущего значения входа b (вид этой модификации определяется значениями ключей и интерпретаций функции доступа необязательного присваивания оператора 5, содержащего выход а). Рис. 11.42. Схема над распределенной памятью А. Для любой О-схемы а существует эквивалентная ей P-схема Р, в которой Ga = Gp и Qa = Qp. Б. Существуют такие P-схемы а, что любая О-схема Р, в которой Ga = Gp и Qa — Qp, не является эквивалентной схеме а. На рис. 11.43 изображена P-схема, не реализуемая схемой над общей памятью, удов- летворяющая данному свойству. Путь Р = (S|, ..., 5Г) по P-схеме а называется маршрутом пары (с, d), если с— выход оператора Sl5 d— вход оператора Sr, и не соединен дугой с входом d в Ja ни один из выходов оператора 5Ь отличных от с, и ни один из обязательных выходов внутренних операторов пути Р. Дуга (с, d) графа Ja называется существенной, если в схеме а су- ществует маршрут пары (с, d).
888 Часть II. Применение графов и граф-моделей Рис. 11.43. Пример P-схемы а, не реализуемой О-схемой. P-схема р эквивалентна а и получается вставкой оператора пересылки П. О-схема у реализует P-схему р Например, схема на рис. 11.42 содержит только существенные дуги, а в схеме на рис. 11.44 есть ряд несущественных дуг: например, не является существенной дуга, соединяющая выход преемника оператора старт с входом оператора стоп. В. Если Ja — остов графа содержащий все его существенные дуги, то эквива- лентны схемы а = (Gp, Ja, Qp) и р = (Gp, Jp, Qp). Два операнда называются взаимно достижимыми в P-схеме а, если выполнено хотя бы одно из следующих условий: □ они информационно связны; □ существует полупуть между ними в Ja, проходящий только по существенным дугам; □ существует операнд, который взаимно достижим из каждого из них. Обозначим через L(a) такую P-схему, которая получается из P-схемы а добавлением в Ja всех таких дуг (с, d), что выход с и вход d взаимно достижимы. Говорят, что P-схема а реализуется О-схемой Р (с сохранением эквивалентности), если Ga = Gp, Qa = Qp и схемы а и Р эквивалентны. Г. Если P-схемы а и Ца) эквивалентны, то а реализуется некоторой О-схемой. Д. Для любой P-схемы а, в которой нет необязательных выходов, существует такая эквивалентная ей P-схема Р, что Gp получается из Ga вставкой операторов пере- сылки и р реализуется О-схемой.
Глава 11. Преобразование программ 889 Рис. 11.44. Р-схема с операторами пересылки Алгоритм 11.2. Построение реализуемой Р-схемы Дано. P-схема а, в которой нет необязательных выходов. Требуется. Р-схема (3, которая эквивалентна схеме а и реализуется О-схемой. Метод. Р-схема [3 получается из исходной P-схемы а вставкой операторов пере- сылки, которая осуществляется по следующим правилам. Последовательно рассмат- риваются все выходы а в P-схеме а. Пусть (а, Ь\), (а, Ь2),(а, Ьг) — все существен- ные дуги графа Ja, исходящие из a, a S — оператор с выходом а. На каждой дуге
890 Часть II. Применение графов и граф-моделей уграфа, исходящей из S, размещается в произвольном порядке группа операторов пересылки 77ь П2,..., Пг, причем выход а соединяется дугой с входом каждого из раз- мещаемых операторов пересылки, а выход оператора П, соединяется дугой с входом Ь,. На рис. 11.44 продемонстрирован результат применения алгоритма к Р-схеме рис. 11.42. Заметим, что идея рассмотренного алгоритма заключается в расчленении операторами пересылки каждой существенной дуги информационного графа с целью заведомого нарушения взаимной достижимости операндов каждой пары вход-выход, не образующих дугу информационного графа. Понятно, что для нарушения указанной достижимости совсем не требуется рассекать все существенные дуги информационного графа, а для рассечения дуг информацион- ного графа, исходящих из выхода некоторого оператора S, не обязательно размеще- ние операторов пересылки на все дуги, исходящие из S. На рис. 11.45 и 11.46 приведены примеры способов более удачного (по числу добав- ляемых операторов) размещения операторов пересылки, позволяющие переходить от исходной P-схемы к такой эквивалентной ей, которая реализуема О-схемой. Важно отметить, что если реализуемая (Э-схемой схема [3 на рис. 11.45 получена из схемы a путем нарушения взаимной достижимости каждой пары вход-выход, не принадлежа- щей информационному графу и имеющей хотя бы один подтверждающий ее мар- шрут, то в P-схеме Р, изображенной на рис. 11.46, сохраняется взаимная достижи- мость такой пары (это пара (с, d), где с — выход оператора S3, a d — вход оператора 57). Тем не менее P-схема Р (рис. 11.46) реализуется О-схемой, поскольку оператор Рис. 11.45. Нарушение взаимной достижимости операндов
Гпава 11. Преобразование программ 891 Рис. 11.46. Нарушение условия существования маршрутов пересылки помещен так, что нарушаются условия существования маршрутов, под- тверждающих пару (с, d). 11.3.6. Схематизация программ Пусть имеется класс программ, для каждой из которых задано расчленение ее на эле- менты: операторы и переменные. Задача схематизации состоит в нахождении единых правил перевода любой из заданных программ в такую (как правило, неинтерпрети- рованную) схему (определенного класса), в которой полностью представлена инфор- мационно-логическая структура программы при зафиксированном разбиении ее на элементы. Решение задачи схематизации будет тем лучше, чем уже множества управ- ляющих и информационных связей в схемах, моделирующих одни и те же про- граммы. Обычный переход к схематизации — это локальный перевод, в процессе которого операторы программы переводятся в операторы схемы независимо друг от друга с помощью "безопасных" правил, основанных на семантике конструкций языка про- граммирования. Эти правила, например, предполагают, что оператор перехода по метке, являющейся формальным параметром, может осуществить переход на любой помеченный оператор программы, что оператор присваивания формальному пара- метру процедуры может перевычислить любую переменную программы.
892 Часть II. Применение графов и граф-моделей Для ряда языков программирования, например для языка Фортран, локальный пере- вод позволяет получать приемлемое решение задачи схематизации. Однако для тех языков программирования, в которых широко используется механизм косвенной ад- ресации (например, для языков Алгол-68 или ПЛ/1), локальный перевод приводит при схематизации к таким загрублениям представления программы в виде схемы, что может вообще не иметь смысла применение алгоритмов обработки программы на основе неинтерпретированной схемы, построенной при локальном переводе. Поэтому в общем случае задача схематизации требует применения нелокальных ме- тодов ее решения. В них "безопасные" предположения, на которых базируются ло- кальные методы схематизации, заменяются на те или другие методы нелокального анализа. При этом, чтобы моделирующая схема более точно описывала управляющие и информационные связи между операторами (эта задача является ключевой при схе- матизации), на практике можно использовать разные методы нелокального анализа при схематизации. Например, предварительным просмотром программы можно вы- яснить, какие метки подставляются в качестве фактических параметров процедур, и тем самым ограничить множество преемников оператора перехода по формальной метке в процессе последующего локального перевода. В основе методов нелокальной (глобальной) схематизации лежат так называемые опе- раторные схемы с косвенной адресацией, в которых проинтерпретированы функции доступа к переменным через указатели. 11.3.7. Схемы с косвенной адресацией Как и в программе, память в крупноблочной схеме может быть представлена пере- менными, а оператор может иметь некоторое множество операндов; часть из них яв- ляется (информационными) входами, а часть— (информационными) выходами. Идентификация взаимовлияний операторов и элементов памяти (переменных) осуще- ствляется заданием раскраски, которая сопоставляет каждому операнду операторов некоторую переменную. Переменные, соответствующие входам операторов, называ- ются его аргументами, а выходам —результатами. При своем исполнении оператор может использовать текущие (информационные) значения переменных-аргументов и вычислять новое состояние памяти, изменяя текущие значения переменных-резуль- татов. Таким образом, схема кодирует оба типа отношений, реализуемых между оператора- ми программы при ее выполнении: связь по передаче управления — управляющую связь, когда оператор выполняется непосредственно вслед за другим, а также связь по передаче информации — информационную связь, когда оператор при своем исполне- нии по одному из входов использует информационное значение, выработанное в ре- зультате работы другого оператора по одному из его выходов. При рассмотрении среди переменных особых величин— указателей, значениями которых являются имена других переменных (в частности, указателей), возникают две новые операции: именования (присваивания указателю имени переменной) и разыменования (выборки имени переменной как значения указателя). В соответствии с этим можно рассматривать в крупноблочных схемах операторы именования и
Глава 11. Преобразование программ 893 разыменования, каждый из которых имеет одного преемника, один вход и один вы- ход. Особенностью этих операторов является то, что при своем выполнении оператор разыменования не изменяет значение ни одной переменной, а оператор именования не использует значение ни одной переменной, и, таким образом, оператор именова- ния не имеет аргументов, а оператор разыменования — результатов. Входы операто- ров именования и выходы операторов разыменования будем называть фиктивными. Схема с косвенной адресацией (или KA-схема) а — это тройка (Ga, Ja, Ra) в которой: □ G„ — управляющий граф, вершинами которого являются операторы с приписан- ными им операндами, разделяющимися на входы и выходы; □ Ja — информационный граф, дуги которого исходят из фиктивных выходов; □ Ra — раскраска, сопоставляющая переменные тем операндам, которые не имеют инцидентных дуг в Ja. Всевозможные реализации счета по программам, получаемым различными интерпре- тациями операторов схемы, образуют множество допустимых цепочек ее операторов. Предполагается, что только операторы именования и разыменования могут использо- вать или изменять значения указателей, а информационные дуги, исходящие из неко- торого выхода d, реализуются при каждой выработке имени переменной, которое, возникнув на d при выполнении оператора разыменования с выходом d, немедленно рассылается на те входы Ь, для которых (d, b)— дуга графа Ja. Таким образом, каж- дой допустимой цепочке операторов S|, 52, —, S„... соответствует последовательность раскрасок Ro, R\, R2,..., Rh ..., в которой Ro = Ra и для любого I раскраска /?, однознач- но определяется последовательностью S), S2,..., S, и сопоставляет нефиктивным опе- рандам оператора Si+! результаты и аргументы данного его выполнения. Основной вопрос в исследовании схемы с косвенной адресацией состоит в нахожде- нии покрывающих множеств для аргументов и результатов операторов и информаци- онных связей схемы. Нетрудно видеть, что такие дуги (d, b) графа J„, когда нет пути от оператора с выхо- дом d к оператору с операндом Ь, не влияют на множества аргументов и результатов операторов схемы, а также на ее информационные связи. Поэтому в дальнейшем предполагается, что схема не содержит таких дуг. По аналогичным соображениям рассматриваются только такие схемы, в которых нет вершин, недостижимых от на- чального оператора. Предполагаем, что в множестве всех выходов операторов выде- лено такое подмножество В, что в каждый момент выполнения оператора с выходом d е В некоторая переменная (не обязательно одна и та же для всех его выполнений) сопоставлена выходу d и обязательно получает новые значения всех своих элементов. На рис. 11.47 приведен пример /Gl-схемы, описывающей следующий фрагмент про- граммы начало 1. x,z : целый; 2. проц Г(у) = 3. у:=у+1
894 Часть II. Применение графов и граф-моделей 4. все; 5. ввод х; ввод z; 6. если х > z то 7. вызвать f(x) 8. иначе х := х + z 9. вызвать f(z) 10. все; 11. вывод х; вывод z; конец Предполагается, что параметр процедуры подставляется по ссылке. Дуги информаци- онного графа изображены штриховыми стрелками. Для всех i оператор S, схемы со- ответствует z-й строчке в записи программы. Оператор S2— оператор разыменова- ния, а операторы Sy и Sg — операторы именования. старт Рис. 11.47. Пример схемы с косвенной адресацией Отображение цт, сопоставляющее каждому операнду d схемы а подмножество называется псевдораскраской. Псевдораскраска у называется точной (обозначается 1|та), если для любых х и d х е (d) тогда и только тогда, когда существует такая ин-
< Глава 11. Преобразование программ 895 терпретация, при которой в момент выполнения оператора с операндом d переменная х сопоставляется операнду. Говорят, что псевдораскраска ц/ точнее псевдораскраски ф" (обозначается у"), если 1|/' (d) cz у" (d) для всех d, и строго точнее \р" (обозначается цт' -< цт"), если ф'(<7) < y"(d) и ф' ф ф". Между выходом d оператора S, и входом Ь оператора S2 имеется информационная связь по переменной х относительно псевдораскраски у (или у-исвязь), если d и Ь не являются фиктивными, и существует путь от S, до S2, внутренние операторы которого не имеют таких выходов с, что с е В и у(с) = {х}. А. Каждая информационная связь схемы является уа-исвязью, а для любых псевдо- раскрасок \|Г и ц/", если а < 1|/' =< у", то множество \\Г-исвязей содержится в мно- жестве -исвязей. Псевдораскраска у называется корректной, если <|/(c/)={/?tI(cZ)} для всех тех операн- дов d, которые не имеют инцидентных дуг в J„, и >]/(</) g y(fe) для любой дуги (d, Ь) графа Ja и любых таких фиктивных du Ь, что между оператором с входом d и опера- тором с выходом b имеется у-исвязь. Б. Для любой корректной псевдораскраски щ \|/а < у и множество у-исвязей содер- жит все информационные связи схемы. В. Существует минимальная корректная псевдораскраска, которая точнее любой другой корректной псевдораскраски. Псевдораскраска у" называется замыканием псевдораскраски ф' (обозначаем щ" = ф), если для любого операнда d и переменной х х е у"(<7) тогда и только тогда, когда выполнено одно из следующих условий: □ х е ф' (d), и d не имеет инцидентных дуг в J„; □ хе \\i"(d), n(b,d) — дуга графа J„; □ существует у'-исвязь между оператором именования с таким входом е, что х е цт'(е), и оператором разыменования с выходом d. Г. Замыкание любой корректной псевдораскраски у корректно и точнее, чем щ. Если V — минимальная корректная псевдораскраска, то у = vj7 . Д. Существуют такие KA-схема а и ее корректная псевдораскраска ф, что у = vp w V * Ш Пример такой схемы изображен на рис. 11.48. Здесь S2, S5, S2 — операторы имено- вания, a S4 и — операторы разыменования. Пусть a, b,c,d— выходы операторов 54, <S5, S(„ S2 соответственно. Нетрудно видеть, что и \|/2, для которых Vi(a) = V,(fe)= {z,y}, \|/,(с) = Vi(t/)= {v,x}, V2(a) = \|/2(fe)= {z}, ф2(с) = V2W = {v} и Vi(e)= V2(e) = {Яа(е)} для всех других операндов е, являются корректными псевдо- раскрасками, совпадающими со своими замыканиями.
896 Часть II. Применение графов и граф-моделей 11.3.8. Корректные псевдораскраски Начнем с рассмотрения так называемых правильных /61-схем, в которых каждый ука- затель и каждый операнд имеют фиксированный конечный ранг. Под рангом пере- менной понимается максимальное возможное число применений операции разымено- вания к текущему состоянию переменной, а под рангом операнда— текущий ранг переменной, сопоставленной данному операнду. Обозначим через г функцию, сопос- тавляющую переменным и операндам правильной /61-схемы их ранги. Алгоритм 11.3. Нахождение минимальной корректной псевдораскраски Дано. Правильная /С4-схема. Требуется. Минимальная корректная псевдораскраска у схемы а и множество у-исвязей. Метод. В качестве у берется последний элемент последовательности ц/*, у* ’,..., 1д°, в которой k = max{r(x): х е Ха}, у * равно {/?а}, если Ra на d определено, и рав- но 0 в противном случае, а для любого i псевдораскраска ц/' 1 получается из у' сле- дующим двухэтапным процессом. На первом этапе устанавливаются ц/'-исвязи по переменным из Л, = {х : г(х) = /}. Второй этап — это перевычисление до стабилизации у' по следующему правилу: если существует такая пара фиктивных операндов due, что между оператором с входом d и оператором с выходом е найдена на первом этапе у'-исвязь и ч/(<7)\ф (е) * 0, то для всех операндов с, достижимых из е в Ja, i/(c) заменяется на ч/(с) ° 'До- полученная после завершения второго этапа псевдораскраска и рассматривается в качестве ц/'- .
Глава 11. Преобразование программ 897 А. Алгоритм всегда завершается через конечное число шагов построением мини- мальной псевдораскаски и множества ху-исвязей. Однако для Л/1-схем общего вида нельзя задать порядок обработки переменных, ко- торый позволил бы найти минимальную корректную псевдораскраску. Для того что- бы обойти эту трудность, можно использовать так называемый граф косвенной адре- сации. Говорят, что значение ранга I переменной х сопоставлено в схеме о операнду d, если либо /=0 и Ra(d) = x, либо существует последовательность операндов (а}, а2, Ь2, a/,b I, ац в которой ац , = d, Ra{a\)~x, (bt, а, + 1) — дуга графа Ja и для любого i операнды а, и h, — это вход и выход оператора разыменования. Граф с косвенной адресацией (KA-граф) определяется как минимальный граф Га, вершинами которого являются переменные X, удовлетворяющий следующему усло- вию для любых х, у, w, v, t, Г. если в а существует оператор именования, входу кото- рого сопоставлено значение ранга t переменной х, а выходу — значение ранга t пере- менной у и в Га существуют пути отх к w длины I и от у к v длины t, то пара является дугой графа Га. Б. В KA-графе Га правильной KA-схемы а для любой дуги (х, у) выполняется г(х) = г(у) + 1. Алгоритм 11.4. Построение корректных псевдораскрасок Дано. /С4-схемаа. Требуется. Корректная псевдораскраска у схемы а и множество \у-исвязей. Метод. Последовательно выполняются следующие этапы: построение /<Л-графа Га; вычисление начального состояния у” псевдораскраски у; многократная замена теку- щего состояния \|/ псевдораскраски ц/ на состояние ц/ + 1 = Д7/, выполняемая до тех пор, пока не будет получено такое первое состояние удля которого у '= щ'. Начальное состояние вычисляется следующим образом. Вначале для любого d значение устанавливается равным множеству тех переменных X, которые сопос- тавлены операнду d раскраской Ra, а затем до стабилизации многократно происходит перевычисление ту0, обязательно расширяющее у0 и состоящее в следующем его из- менении относительно некоторого оператора именования S. Пусть d— выход опера- тора S, Е — множество операндов, достижимых в Ja из выхода S, a Y — множество таких переменных х, что (z, х)— дуга графа Га для некоторой z е Тогда для любого b е Е значение y°(J) заменяется на хр°(<7) U Y. В. Алгоритм всегда останавливается через конечное число шагов и строит такую последовательность корректных псевдораскрасок <|Д тр/1,..., У|/, в которой ц/ ' 1 -< ф' для любого Z, и если а является правильной и к — ее максимальный ранг, то г < к и цЛ — минимальная корректная псевдораскраска. В рамках KA-схем были описаны методы нахождения информационных связей и множеств аргументов и результатов в программе, содержащей указатели. При этом предполагалось, что управляющие связи в программе уже известны. 29 Зак 202
898 Часть II. Применение графов и граф-моделей Заметим, что задачи более точного нахождения информационных и управляющих связей взаимосвязаны и могут быть решены следующим образом. На первом этапе устанавливаются управляющие связи в рамках предположения об аргументах и ре- зультатах операторов, получаемых по графу с косвенной адресацией. На основе управляющих связей строятся информационные связи и уточняются множества аргу- ментов и результатов операторов. Более точная информация об аргументах и резуль- татах операторов и информационных связях между операторами позволяет уточнить управляющие связи, что приводит к более точному построению информационных связей и множеств аргументов и результатов операторов и т. д. В рамках Л74-схемы можно получать более точные решения задачи схематизации, если сделать дополнительные ограничения в определении ф -исвязи. Содержатель- ный смысл этих условий— это требование согласованности путей реализации пере- дачи значения через переменную и передачи имени этой переменной через указатель, а также путей передачи имени данного указателя через указатель следующего уровня и т. д. Отсутствие таких согласованных путей гарантирует отсутствие соответствую- щей информационной связи по данной переменной в любой моделируемой схеме. 11.3.9. Модель аннотированных программ Исследование систем преобразований и их использований для различных видов рабо- ты с программами показали важность учета при преобразованиях априорно известной информации о применениях преобразуемой программы, существенность при работе с программами не только эквивалентных преобразований, сохраняющих функцию, реа- лизуемую программой, но и таких преобразований, которые сужают или расширяют эту функцию: сужающих или обобщающих преобразований. Как показывают иссле- дования смешанных (частичных) вычислений, представляющих определенную фор- мализацию сужающих преобразований в виде вычислений программ при частично заданных входных данных, многие виды практически полезной работы с программа- ми оказываются не чем иным, как процессами смешанных вычислений. Рассмотрим модель аннотированных программ, позволяющую рассматривать про- цессы обработки программ в рамках известной информации об их применениях, представленной в виде формализованных комментариев— аннотаций. Класс кор- ректных преобразований аннотированных программ охватывает различные виды ра- боты с базисными программами. В рамках модели аннотированных программ выра- зимы эквивалентные и такие неэквивалентные преобразования программ, как выпол- нение, смешанное выполнение, специализация и др. Пусть имеется множество переменных V= {v} и множество состояний памяти S= {s} — частичных функций, сопоставляющих переменным v их текущие значения s(v). Таким образом, для каждого s е S задано разбиение множества К на подмноже- ства доступных /l(s), т. е. имеющих значения при данном s, и недоступных I(s) пере- менных, для которых текущее значение s(v) при состоянии памяти s не определено. Говорят, что два состояния памяти s' и s"равны на некотором Же К, если для всех v е W либо s'(y) = s"(v), либо v е (/(s') IT /(s")). Состояние s' расширяет s" (обозна- чение s" < s'), если s' и s" равны на A(s").
Гпава 11. Преобразование программ 899 Программой л называется шестерка (g,/ р, г, a, d), состоящая из: □ уграфа g = (X, U, х0, у0) — ориентированного графа с выделенными начальной х0 и конечной у0 вершинами такими, что из х0 исходит единственная дуга, обозначае- мая через и0 (т. е. OUT(x0)={m0}), и нет дуг, заходящих в х0 или исходящих из у0, (т. е. IN(x0) = OUT(y0) = 0); для каждой дуги и = (х, х') е U определены функции началами) = х и конец(и) = х'; □ функции преобразования памяти f: X—> (S —> S); □ функции следования р '.(Х\ {у0}) —> > <7); □ функций аргументов и результатов а, г : X —> (S —> 21); □ предиката применимости d : X—>(S—> {true, false}) такого, что для всех v е V, х е Хи s, s', s" е Sсправедливы следующие свойства: • s и/(х)(х) равны на PV(x)(s); • если s' и s" равны на a(x)(s'), то d(x)(s') = d(x)(s"), p(x)(sr) = p(x)(s"), a(x)(s/) = a(x)(s"), r(x)(s/) = r(x)(s"), а также/(х)(х/) n/(x)(s'') равны на r(x)(s'); • p(x)(s) e OUT(x). Каждая программа л реализует некоторую функцию л : S —> S, определяемую по сле- дующим правилам. Значение л для некоторого заданного s определено (л применима к s) и равно состоянию памяти s', т. е. л(«) = s' если существует такая конечная после- довательность протокол^, s) = (s° = s, х1 = х0, s’, и',..., х, s', и", хп+ 1 =у0, s”+ 1 = s'), что для любого i справедливы следующие свойства: истинно значение d(x')(s' '), s'=/(x')(s' ’), u' = p(x')(s' ’), х' = конец(и ’). Если конечной последовательности про- токол^, s) не существует, то л не применима, к s и значение n(s) не определено. Если значение л(я) определено, переменные v е a(x0)(s) называются аргументами л(«). Другими словами, выполнение оператора х на некотором состоянии памяти s нор- мально завершается, если d(x)(s) истинно, и состоит в определении нового состояния памяти fix)(s) и выборе нового оператора для исполнения конец(р(х)(у)). Во время данного его выполнения только значения переменных v е a(x)(s) могут использовать- ся и только значения переменных v е г(х)(х) могут измениться. Пусть л'и л" — две программы, л" обобщает (или, что то же самое, является суже- нием) л', если для любого состояния памяти s' к которому л'применима, существует такое состояние памяти s", совпадающее с s'на множестве аргументов л'(s'), что л" применима к s" и n'(s') = n"(s"). л" вычисляет л', если л" применима к любому со- стоянию памяти s', к которому л' применима, и ti'(s') = id'(sr). л' и л" эквивалентны, если они вычисляют одна другую. Пусть задано непустое множество объектов, называемых аннотациями, распадаю- щееся на два непересекающиеся подмножества: утверждения Е = {е} и директивы Q = {q}. Каждое утверждение е е Е— это предикат на S, задающий разбиение S на два множества: допустимых е+ и недопустимых е состояний памяти относительно е. Цо обозначает тождественную директиву, т. е. qo(s) = s для всех s е S.
900 Часть II. Применение графов и граф-моделей Аннотированной программой л' называется тройка (л, т, t), где л — базисная про- грамма (обозначаемая через йже(л')), a m\X<J Е иг: U Q— функции анно- тирования, которые сопоставляют каждому оператору х программы л некоторое ут- верждение т(х) е Ей каждой ее дуге и некоторое утверждение т(и) е Е и некоторую директиву q(u) е Q. Для заданного .v е S значение л'(л) определено (л' применимо к а) и равно состоянию памяти s', т. е. л'(«) = s', если существует такая конечная последовательность прото- кол^', s) = (У0 = s, х1 = Хо, •$*, и, s’, х2, s2, и2, s2,..., х", s" , и , Г, х" + 1 = уо> ?'+1 = s'), для которой при любом I справедливы следующие свойства: d(x')( s'~l) истинно, s' = =/fx')(s'-1), 'll = p[x')Cs'~'), x = конец(и'~1), s' e (/w(w'))', e (/n(x'))+, S' = t(u')(s‘). Таким образом, подобно базисной, аннотированная программа л' вычисляет некото- рую частичную функцию л': S —> S. Поэтому отношения эквивалентности, вычисляе- мости и обобщения, определенные для базисных программ, можно рассматривать для всего класса П базисных и аннотированных программ. Программа л' называется квазибазисной, если в ней (m(x))+ = S для любого хеА' а также (ти(и))+ = S и t(u) = <?о для любой и е U. Программа л' называется хорошо определенной, если base(y.') обобщает л'. А. Любая квазибазисная программа л эквивалентна программе base(n'), причем для любого состояния s, к которому л' применима, последовательность прото- кол(Ьа:<е(п), s) получается из протокол^, s) удалением всех s' ив них s' = s'1 = s' для всех i. Б. Аннотированная программа л является хорошо определенной, если существует такое W с V, что для всех х е X, s е 5, и е U справедливы следующие свойства: со- стояния памяти t(u)(s) и s равны на W, a(x)(s) cz И' и r(x)(s) с W. Предполагается, что язык аннотированного программирования получается расшире- нием обычного языка программирования, называемого базисным. Базисный язык расширяется возможностью записи в синтаксической форме комментариев аннота- ций, относящихся к различным точкам программы. При этом средства аннотирования таковы, что любая базисная программа эквивалентна самой себе как аннотированной программе (т. е. рассматривается как соответствующая квазибазисная аннотирован- ная программа). 11.3.10. Преобразования программ Преобразованием называется любая функция h : П —> П. h — корректное (обобщаю- щее, сужающее, эквивалентное) преобразование, если для любой исходной програм- мы л е П результирующая программа /г(л) вычисляет (обобщает, сужает, эквивалент- но) л. Пусть на множестве П задано некоторое отношение частичного порядка которое будем называть отношением качества программ: л'<л", если л' качественнее л". ‘
Гпава 11. Преобразование программ 901 Программа л' называется конкретизацией программы л относительно < (обозначаем л' е ЛГ(л, <), если л'< лил' вычисляет программу л. Конкретизация л' программы л относительно < называется полной, если л' < л" для любой л" е К(л, <). Преобразо- вание h называется конкретизирующим (специализирующим) относительно критерия качества <, если А(л) е ЛГ(л, <) для всех л е П. Важный подкласс конкретизирующих преобразований образуют преобразования, ко- торые изменяют лишь утверждения в преобразуемой программе. К этому классу пре- образований, которые естественно называть анализирующими, относятся преобразо- вания, направленные на решение задач верификации, а также преобразования, осуще- ствляющие решения задач потокового анализа при оптимизации программ. Рассматривая различные отношения качества программ, обычно используемые на практике, в классе конкретизирующих преобразований можно выделить следующие основные подклассы конкретизирующих преобразований: П оптимизирующие преобразования, направленные на повышение эффективности программ (они улучшают программу в традиционном для оптимизирующих пре- образований смысле, но с учетом разнообразия трансляторов и сред исполнения: операционных систем и ЭВМ); П преобразования, назначением которых является повышение самодокументируемо- сти и наглядности аннотированной программы (такого типа преобразования могут пополнять программу утверждениями о ее свойствах, а также преобразовывать ба- зисную программу, осуществляя в ней переименование объектов, вставку явных описаний, улучшение структуры программы и т. д.); П преобразования, осуществляющие построение отладочной версии программы (они пополняют базисную программу набором операторов, проверяющих справедли- васть указанных в аннотациях свойств при исполнениях базисной программы); П преобразования, назначением которых является статическая проверка правильно- сти программ (такие преобразования, например, могут выявлять так называемые свойства неправдоподобности программ, связанные с определенными несоответ- ствиями между программным текстом и множеством представляемых им испол- нений, свидетельствующими о возможных содержательных ошибках, присутст- вующих в программе). Подклассы преобразований, конкретизирующих программы относительно разных критериев качества, обычно используемых на практике, имеют непустое пересечение. Преобразования из этого пересечения получили название редуцирующих. Для построения преобразователей аннотированных программ можно использовать идею так называемой трансформационной машины — некоторого абстрактного вы- числительного устройства, данными которой служат аннотированные программы, а командами— преобразования программ. Дело в том, что различные процессы кор- ректного преобразования аннотированных программ в значительной степени опира- ются на сравнительно небольшое число преобразований, являющихся корректными в классе аннотированных программ. В трансформационной машине выделяются три типа команд: команды движения по обрабатываемой программе, выделяющие в ней одну или несколько точек активности
902 Часть II. Применение графов и граф-моделей ---------------------------------------------------------1--------------- для применения элементарных преобразований; управляющие команды, предназна- ченные для структурирования и выстраивания других команд; трансформации — элементарные преобразования, которые одни только могут менять обрабатываемую программу. При этом, проблема того, что некоторая программа трансформационной машины реализует конкретизацию, по-существу, сводится к более простым пробле- мам остановки программы и направленности преобразования, реализуемого про- граммой. Библиографический комментарий Эрбран в 1930 г. (в диссертации) предложил недетерминированный алгоритм вычисления унификатора двух термов. Эта работа была вызвана интересом к решению уравнений. Однако современное использование и понятие унификации принадлежат Робинсону. В своей пионер- ской работе [135] Робинсон предложил метод доказательства теорем, основанный на резолю- ции— некотором мощном правиле вывода. Центральной в методе была унификация термов первого порядка. Робинсон доказал, что два терма первого порядка, если они унифицируемы, имеют единственный наибольший общий унификатор (НОУ). Он предложил алгоритм для вычисления НОУ и доказал его корректность. Этот алгоритм был крайне неэффективен, имел экспоненциальную временную и емкостную сложность, поэтому в дальнейшем большие уси- лия многих авторов были направлены на улучшение алгоритма унификации. Они завершились разработкой ряда эффективных алгоритмов [ 103, 106, 120, 125, 1331, основные три из которых приведены в разд 11.1. Корбин и Бидуа [88] "реабилитировали” исходный алгоритм Робинсо- на путем использования в нем новых структур данных. Они понизили его экспоненциальную временную сложность до О(и2), утверждая, что этот алгоритм более прост, чем алгоритм Мар- телли-Монтанари, и на практике превосходит его по эффективности. Задача унификации и ряд ее вариантов рассматривается в обзорной работе [120]. В ней обсуж- даются различные алгоритмы и структуры данных, дается обзор исследований по унификации, возникающих в таких областях информатики, как доказательство теорем, логическое програм- мирование и обработка естественных языков. Работа содержит примеры, освещающие кон- кретные использования унификации и встречающиеся там специальные проблемы. Среди рас- сматриваемых тем — резолюция, логика высших порядков, проверка вхождений, бесконечные термы, эквациональные теории, параллельные алгоритмы, структуры и другие приложения унификации. Семи-унификация является обобщением как поиска по образцу, так и обычной унификации: для некоторой заданной пары термов s и t нужно найти две такие подстановки рис, что P(g(s)) = о(г). В статье [ПО] представлена разрешающая процедура для семи-унификации, ко- торая основана на технике, аналогичной используемой в процедуре пополнения Кнута- Бендикса. Когда ее входные термы семи-унифицируемы. процедура строит каноническую СПТ, из которой подстановки р и о легко извлекаются. Хотя она работает в экспоненциальное время, время работы разрешающей процедуры, как показывают авторы, может быть сделано полиномиальным. Существует целый ряд обзорных работ [10, 15, 57, 83, 84, 137], посвященных наиболее важ- ным результатам, методам и открытым проблемам теории систем переписывания Доказательство теоремы Биркхоффа может быть найдено в работе [82], теоремы Ньюмена — в [130], теоремы Кнута-Бендикса-Уэ— в [104, 121], теоремы Крушкаля-Наша-Вилиамса — в [122, 129], теоремы Метивиера— в [127] и теоремы Шмитта — в [137].
Гпава 11. Преобразование программ 903 Обзором методов обращения с равенствами в процедурах революционного типа является рабо- та [105]. В ней рассматриваются различные стратегии унификации и процедуры в стиле алго- ритма Кнута-Бендикса, используемые при автоматическом доказательстве теорем. Прямые методы доказательства нетеровости СПТ, не требующие подходящего упорядочения на функциональных символах, рассматриваются в [91, 100]. Эти методы основаны на непо- средственном анализе правил переписывания и являются более "алгоритмическими", но при- менимы для меньшего числа СПТ. Разрешимость свойства конфлюэнтности для СПТ, правила которых не содержат переменных, показана в [132]. Наряду с равенствами для спецификации абстрактных типов данных и в других приложениях используются так называемые условные равенства, т. е. формулы вида = tt Л ... Л s„ = = t„—>5„+| = г„+|. Использование аксиом такого вида не нарушает "хороших" свойств специфи- кации (существование инициальной модели), но дает более удобное и мощное средство [139]. Для реализации таких спецификаций развивается аппарат условных СПТ [95, 109, 128]. Уже отмечалось, что алгоритм пополнения, кроме успешного завершения, может работать бесконечно долго или останавливаться "с неуспехом" ввиду невозможности ориентировать равенство. Причина бесконечной работы может быть устранена введением дополнительных функциональных символов [100, 121], а причина остановки "с неуспехом” (например, наличие закона коммутативности fix, у) =fiy, х)) связана с принципиальным недостатком всего алго- ритма. Для преодоления этого недостатка имеется ряд модификаций алгоритма Кнута- Бендикса, основанных на идее выделения равенств типа ассоциативности-коммутативности в отдельную теорию Т и рассмотрении равенств термов с точностью до эквивалентности " =т " [105, 107, 131]. Методам доказательства нетеровости, основанным на упорядочении, посвящено большое чис- ло работ, ссылки на которые могут быть найдены в [57, 92, 137]. Отметим среди них лишь работу [80], содержащую мощный и элегантный метод доказательства корректности больших классов "Кнута-Бендикса-подобных" алгоритмов пополнения. Граф-модели стали применяться в программировании одновременно с его появлением. Это, в первую очередь, управляющий граф и другие граф-модели программ, графовые модели струк- тур данных, граф-модели для решения ресурсных задач и др. Классификация таких моделей с самой общей точки зрения предложена в [14]. Толковый словарь [18] содержит наиболее упот- ребительные термины по теории графов в информатике и программировании. Концепция управляющего графа как модели программы, описывающей структуру ее управ- ляющих связей, впервые рассматривалась в работах В. В. Мартынюка [62—63]. Исследование свойств управляющего графа и описание применений можно найти в многочисленных книгах и обзорах по методам трансляции и оптимизации программ ([4, 13, 15—17, 22—23, 34, 37, 40—42, 47, 51—52, 78, 102] и др.). Следует отметить появившийся одним из первых обзор по графовым моделям программ Б. А. Головкина [9], а также обзор задач анализа управляющих графов В. Н. Касьянова [47]. Широкий круг методов и алгоритмов, связанных с управляющим графом, рассмотрен в книгах [15—16, 102]. Требования к промежуточному представлению программ заимствованы из работ [42] и [134], более подробно о зависимости по данным можно прочесть (на русском языке) в статье [2], а также в [12, 20]. Описание графа программных зависимостей (ГПЗ) и формальное определение зависимости по управлению взято из статьи [97] (русский перевод [74]). ГПЗ нашел достаточ- но широкое применение, и ему посвящено большое число публикаций. Дальнейшим развитием ГПЗ является сеть программных зависимостей (СПЗ) [81], [11], объединяющая достоинства ГПЗ и представления программы в виде так называемой SSA-формы (см. [79—80]). Описание иерархического графа заданий дано по работам [19, 98—99]. В отличие от ГПЗ, ори- ентированного в основном на векторные машины, ИГЗ рассчитан на мультипроцессоры, но
904 Часть II. Применение графов и граф-моделей может быть использован и для других архитектур, в частности, для архитектур, эксплуати- рующих мелкозернистый параллелизм. Специально для таких архитектур был разработан идеограф — теоретико-графовое представление, в котором зависимости по данным и по управ- лению рассматриваются вместе [140, 142]. Понятие схемы программ принадлежит А. А. Ляпунову и было введено им в 1953 г., исходя из общей концепции необходимости и возможности формализации процесса программирования. Первыми "заказчиками" математических моделей программ стали разработчики трансляторов, которые в конце 50-х и начале 60-х годов XX века столкнулись с необходимостью обоснова- ния алгоритмов оптимизирующей трансляции и доказательства их корректности. В настоящее время теория схем программ — это широко разветвленная область исследования, содержащая много фундаментальных результатов не только по операторным моделям последовательных программ, но и по рекурсивным схемам и схемам параллельных программ. Знакомство с этой областью исследований можно начать с обзора [27] и монографий [17, 42, 54 —55]. Оператор- ные схемы для параллельных языков программирования рассматривались в работах [1, 5—8, 32, 101]. Первым всесторонне исследованным классом схем программ были схемы Янова. В работе Ю. И. Янова [56] впервые выделены и формализованы основные компоненты теории схем и, в первую очередь, — понятие схемы программ и отношение эквивалентности. Яновым были найдены алгоритмы распознавания эквивалентности в этом классе схем, построена полная система преобразований, позволяющая трансформировать друг в друга любую пару эквива- лентных схем. Схемы Янова активно изучались в различных модификациях и обобщениях. Ратледж [136] упростил доказательство разрешимости эквивалентности, моделируя простые схемы Янова конечными автоматами, дал независимое определение функциональной эквива- лентности схем Янова и доказал равнообъемность функциональной и формальной эквивалент- ностей. В работе А. П. Ершова [25] было введено представление схем Янова в виде графов. Это позво- лило упростить аксиоматику, сделав ее в то же время более полной, в частности, аксиоматизи- ровав с помощью разметки понятие достижимости операторов и допустимости наборов. Рабо- та А. П. Ершова дала импульс новым исследованиям схем Янова, особенно изучению различ- ных обобщений этих схем. Ю. И. Янов [77] исследовал вопрос о том, можно ли заменить нелокальные схемы правил сис- темы преобразований схем Янова конечным числом локальных правил, установил, что в об- щем случае это сделать нельзя, и нашел положительное решение для класса простых схем Янова. В. К. Сабельфельд [71] нашел общий критерий локальности системы эквивалентных преобразований схем Янова. В. Э. Иткин [30] и Каплан [108] доказали разрешимость пробле- мы эквивалентности для схем Янова с повторными вхождениями одного и того же оператора. В. Э. Иткин построил также полную систему преобразований для этого случая. В. А. Тузов [72—73] исследовал схемы Янова с перестановочными преобразователями, установил разре- шимость эквивалентности для такого обобщения схем Янова. Аналогичный результат был получен А. А. Летичевским как частный случай полугрупповой эквивалентности [61]. Р. И. Подловченко [66—67] ввела и исследовала недетерминированные схемы Янова, в кото- рых вершины-распознаватели заменены вершинами-фильтрами; она показала, что для любой схемы Янова можно построить эквивалентную недетерминированную схему, продемонстриро- вала разрешимость проблемы эквивалентности и построила полную систему эквивалентных преобразований. Термин "стандартная схема программы" предложен В. Э. Иткиным и А. Г1. Ершовым [27, 29] по отношению к классу схем, который в разное время рассматривался разными авторами. Н. А. Криницкий в своей диссертации в 1959 году и в работе [56] исследовал проблему эквива- лентности и эквивалентных преобразований стандартных схем, причем для подкласса схем без
Глава 11. Преобразование программ 905 циклов им был найден алгоритм распознавания эквивалентности и была построена полная сис- тема эквивалентных преобразований. Графовая форма схем была предложена Л. А. Калужни- ным [31]. Неразрешимость проблемы функциональной эквивалентности и других главных проблем для стандартных схем была установлена почти одновременно и независимо Лакхэ- мом, Парком, Патерсоном [124] и А. А. Летичевским [59—60]. Определенный вклад в развитие теории и методов оптимизирующей трансляции на базе опера- торных схем принадлежит В. Н. Касьянову [36, 38, 43—45, 49—50, 53, 112, 118—119]. Он разработал теорию крупноблочных схем, охватывающую известные классы и модели оптими- зации программ с их расширениями на программы со структурами данных и действий и на задачи обоснования корректности по отношению к классам реальных программ. На базе тео- рии крупноблочных схем им были разработаны новые методы исследования основных классов оптимизаций и для каждого класса получены обобщающие результаты, в том числе по обосно- ванию известных систем преобразований, по разработке новых более мощных систем оптими- зирующих преобразований и по построению полных систем эквивалентных преобразований. Он показал, что крупноблочная схема является универсальной моделью программ, обладаю- щей свойствами эрбраповости и полноты сточки зрения укрупненного моделирования Для класса простых схем, моделирующих линейные участки крупноблочных программ (линей- ные программы) с учетом свойств предметной области, В. Н. Касьяновым [32, 50] были разра- ботаны полная система эквивалентных преобразований, а также набор оптимизирующих пре- образований, содержащий для каждой трансформации, помимо схемного, целый спектр преоб- разований. различающихся глубиной семантических свойств, используемых в контекстных условиях. В рамках кратных схем, моделирующих участки повторяемости крупноблочных программ, В. Н. Касьяновым [49, 114] были найдены критерии эквивалентности групповых вынесений операторов и показано, что такие преобразования даже в классе схем со скалярными перемен- ными являются более мощными, чем пооператорные преобразования, исследованные в работах И. В. Пол осина и О. В. Югриновой [68—70]. Первой работой, рассматривающей экономию памяти как самостоятельный этап в процессе программирования, была статья В. С. Штаркмана [75]. В ней по существу была полностью решена задача экономии памяти в линейных программах. Принципиальный вклад в решение задачи об экономии памяти внес С. С. Лавров своей работой [58]. Он ввел понятие оператор- ной схемы, моделирующей программы со скалярными величинами, рассмотрел различные варианты распределения памяти как эквивалентные преобразования, состоящие в переобозна- чении величин, ввел понятие маршрута, канонического распределения памяти и графа несо- вместимости. С помощью схем, предложенных С. С. Лавровым [58] и в дальнейшем получивших название "схем Лаврова" [27], был получен первый значительный результат теории схем программ, а именно — сформулирована в терминах формальных схем и решена задача минимизации числа переменных в программе (задача экономии памяти). Схемы Лаврова нашли свое применение для решения широкого класса прикладных задач теории программирования — главным обра- зом, для алгоритмов оптимизации программ. По существу, это подкласс крупноблочных схем без необязательных операндов вместе с заданным на нем отношением информационной экви- валентности. Завершение построения общей теории перераспределения и экономии памяти для случая ска- лярных величин связано с работами А II. Ершова [21. 24, 28]. Ему же принадлежит наиболее полное ее изложение [24]. Первый шаг в сторону решения задачи экономии памяти для программ, содержащих массивы, был сделан А. П. Ероговым в работе [26] Для этого каждой величине приписывался "вес" —
906 Часть II. Применение графов и граф-моделей целое число, указывающее, сколько рядом расположенных ячеек требуется для хранения вели- чины. В. В. Мартынюк [64] предложил некоторую эвристику совмещения разновесных масси- вов. Вопросы экономии памяти в случае разновесных массивов были рассмотрены также А. С. Никитиным [65]. Указанные результаты по перераспределению и экономии памяти, полученные в рамках схем Лаврова для случая статичности переменных и неструктурности операторов, были обобщены В. Н. Касьяновым на весь класс крупноблочных схем; им же построена полная система преоб- разований, сохраняющих информационную эквивалентность (см. [43], а также [34] и [42]). Опыт практического применения теории экономии памяти в конструировании транслятора был получен при проектировании Альфа-транслятора [3]. Вопросы представления памяти в схемах программ первым начал изучать А. П. Ерщов. В ра- боте [24] им были введены понятия О-схемы и P-схемы Лаврова, рассмотрен переход от О-схемы к эквивалентной ей P-схеме, показано существование /’-схем, для которых нет вычис- ляющих их О-схем с тем же управляющим графом, и доказана возможность перехода от P-схемы к вычисляющей ее О-схеме с помощью операторов пересылки. В. И. Иткин [28] на- шел необходимое и достаточное условие реализуемости заданного информационного графа схемой Лаврова. Описываемые в главе 8 критерии и методы реализуемости с сохранением эк- вивалентное™ P-схем О-схемами были разработаны В. Н. Касьяновым [34—35, 42]. В последние годы широкое применение в теории и практике оптимизирующей трансляции получила так называемая SSA-форма (Static Single-Assignment) представления программы, существенно упрощающая алгоритмы анализа и преобразования программ [79, 89—90]. По- существу, SSA-форма является таким представлением программы в виде P-схемы, в которой каждому входу любого оператора сопоставлен ровно один выход. Данное свойство позволяет рассматривать указанную P-схему в виде О-схемы (именно она и называется SSA-формой), в которой переменными являются выходы операторов. Поскольку в общем случае программа может содержать информационно достижимые выходы операторов, приведение программы к SSA-форме не всегда может быть осуществлено лишь за счет перераспределений памяти в программе. Для некоторых программ нельзя обойтись без вставок в программу специальных операторов (обобщенных операторов пересылки) вида у := ф(х* ), производящих в зависимости от пути попадания в этот оператор выбор одной из переменных х, и пересылку ее значения в переменную у. В современных языках программирования существует широкий набор средств, позволяющих осуществлять неявный (косвенный) доступ к тем или другим информационным объектам (че- рез разыменование указателей, формальные параметры, процедурные переменные, выборку элементов массивов, полей записей и т. д.), и, тем самым, затрудняющих задачу схематизации программ. Поэтому представляется весьма важной задача анализа адресных выражений, полу- чившая на западе название "анализ синонимов" (alias analysis) [86—87, 93—94, 96, 123, 126, 138, 141]. Говорят (см., например, [85]), что две переменные х и у являются "синонимами" (совмещены по памяти), если в некоторой заданной точке программы при исполнении про- граммы через любую из этих переменных можно обращаться к одному и тому же элементу памяти. Рассмотренный в разд. J 1.3 подход к анализу программ, основанный на схемах с кос- венной адресацией, был предложен В. Н. Касьяновым [39] (см. также [34, 42]) и позволяет не только решать задачу синонимов, но и более точно находить множества информационных и управляющих связей. В работах [53, 119] описана реализация этого подхода (в рамках много- языковой системы программирования БЕТА и ее универсального оптимизатора), охватываю- щая различные конструкции адресных выражений, присутствующие в таких языках высокого уровня, как ПЛ/1, Алгол-68, Ада и др.
Глава 11. Преобразование программ 907 Модель аннотированных программ, рассмотренная в разд. 11.3, и понятие конкретизации про- грамм были предложены В. Н. Касьяновым [33, 48]. Исследованиям вопросов анализа и преоб- разования аннотированных программ, а также методов применения преобразований аннотиро- ванных программ для конструирования качественных программ посвящены его работы [111, 113, 115—1161. Список литературы 1. Алгоритмы, математическое обеспечение и архитектура многопроцессорных вычисли- тельных систем. — М.: Наука, 1982. 2. Аллен Р., Кеннеди К. Автоматическая трансляция Фортран-программ в векторную фор- му// Векторизация программ: теория, методы, реализация.— М.: Мир, 1991.— С. 77— 140. 3. АЛЬФА — система автоматизации программирования / Г. И. Бабецкий и др. — Новоси- бирск: Наука, 1967. 4. Ахо А., Ульман Дж. Теория синтаксического анализа, перевода и компиляции.— М.: Мир, 1978. —Т. 1,2. 5. Вальковский В. А. Распараллеливание алгоритмов и программ. Структурный подход.— М.: Радио и связь, 1989. 6. Вальковский В. А. Формальные модели параллельных программ и вычислений. — Ново- сибирск: НГУ, 1984. 7. Вальковский В. А., Касьянов В. Н. Крупноблочная сегментация и распараллеливание схем программ//Программирование.— 1976.—№ 1. — С. 16—26. 8. Воеводин В. В Математические модели и методы в параллельных процессах. — М.: Нау- ка, 1986. 9. Головкин Б. А. Графовые модели программ с вероятностными параметрами. (Современ- ное состояние) // Вопросы радиоэлектроники. Сер. ЭВТ. — 1976. — Вып. 6. — С. 3—26. 10. Дегтярев А. И., ВоронковА А Методы управления равенством в машинном доказатель- стве теорем // Кибернетика. — 1986. —№ 3. — С. 34—41, 49. 11. Евстигнеев В. А. О некоторых формах промежуточного представления программ// Кон- струирование и оптимизация программ. — Новосибирск: ИСИ СО РАН. 1993. — С. 60— 68. 12. Евстигнеев В А. Основы параллельной обработки. Анализ программных зависимостей. — Новосибирск: НГУ, 1996. 13. Евстигнеев В. А. Применение теории графов в программировании. — М.: Наука. 1985. 14. Евстигнеев В. А. Теоретико-графовые модели систем сетевой структуры // Труды ВЦ СО РАН. Сер. Информатика. — Новосибирск, 1994. — С. 78—121. 15. Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки деревьев. — Ново- сибирск: Наука, 1994. 16. Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки бесконтурных графов. — Новосибирск: Наука. 1998. 17. Евстигнеев В А., Касьянов В Н. Сводимые графы и граф-модели в программировании. Новосибирск: ИДМИ, 1999.
908 Часть II. Применение графов и граф-моделей 18. Евстигнеев В. А., Касьянов В. Н. Толковый словарь по теории графов в программирова- нии и информатике. — Новосибирск: Наука, 1999. 19. Евстигнеев В. А., Мирзуитова И. Л. Иерархический граф заданий: свойства и алгоритм построения// Проблемы конструирования эффективных и надежных программ.— Ново- сибирск: ИСИ СО РАН, 1995. — С. 53—69. 20. Евстигнеев В. А., Спрогис С. В. Векторизация программ: анализ зависимостей, 1989.— (НФ ИТМ и ВТ АН СССР; препринт № 23). 21. ЕршовА. П. Аксиоматика распределения памяти// Теория языков и методы построения систем программирования. Труды симпозиума. — Киев: ИК УССР, 1972. — С. 3—21. 22. Ершов А. П. Введение в теоретическое программирование. Беседы о методе. — М.: Наука, 1977. 23. Ершов А. П. Избранные труды. — Новосибирск: Наука, 1994. 24. Ершов А. П. Об операторных схемах над общей и распределенной памятью // Кибернети- ка. — 1968. — № 4. — С. 63—71. 25. ЕршовА. П. Об операторных схемах Янова// Проблемы кибернетики.— М.: Наука, 1967. —Вып. 20. —С. 181—200. 26. Ершов А. П. Сведение задачи распределения памяти при составлении программ к задаче раскраски вершин графа // ДАН СССР. — 1962. — Т. 142, № 4. 27. Ершов А. П. Современное состояние теории схем программ // Проблемы кибернетики. — М.: Наука, 1973. — Вып. 27. — С. 87—110. 28. Иткин В. Э. Критерий реализуемости операторных схем над распределенной памятью // Кибернетика. — 1972. —№ 2. 29. Иткин В. Э. Логико-термальная эквивалентность схем программ // Кибернетика. — 1972, —№ 1, —С. 5—27. 30. Иткин В. Э. Операторные схемы Янова с тождественными операторами // Труды Всесо- юзной конференции по программированию (ВКП—1).— Киев: ИК АН УССР, 1968.— Вып А. — С. 27—46. 31. Калужнин Л. А. Об алгоритмизации математических задач// Проблемы кибернетики.— М.: Физматгиз, 1959. — Вып. 2. — С. 51—67. 32. Карп Р. М., Миллер Р. Е. Параллельные схемы программ // Кибернетический сборник (но- вая серия). — М.: Мир, 1975. — Вып. 13. — С. 5—64. 33. Касьянов В. Н. Аннотирование программ и их преобразование // Программирование. — 1989,—№4.—С. 3—16. 34. Касьянов В. Н. Введение в теорию оптимизации программ. Оптимизирующие преобразо- вания программ и их обоснование. — Новосибирск: ВЦ СО АН СССР, 1985. 35. Касьянов В. Н. К вопросу о реализации схем над распределенной памятью // Кибернети- ка. — 1977. — № 1. — С. 63—68. 36. Касьянов В. Н. К обоснованию алгоритмов преобразования крупноблочных программ // Программирование. — 1981. — № 3. — С. 15—25. 37. Касьянов В. Н. Методы анализа программ. — Новосибирск: НГУ, 1982. 38. Касьянов В. Н. Методы оптимизации программ. —Новосибирск: НГУ, 1984. 39. Касьянов В. Н. О нахождении аргументов и результатов в схемах с косвенной адреса- цией // Программирование. — 1976. — № 1. — С. 6—15.
Глава 11 Преобразование программ 909 40. Касьянов В. Н. Оптимизация программ И Прикладная информатика. — М.: Финансы и статистика, 1983. — Вып. 2. — С. 38—75. 41. Касьянов В. II. Оптимизация программ: обзор подходов. — Новосибирск, 1982.— 43 с. — (Препринт/ АН СССР, Сиб. отд-ние; ВЦ; № 325). 42. Касьянов В. Н Оптимизирующие преобразования программ. — М.: Наука, 1988 43. Касьянов В. Н. Перераспределение памяти в крупноблочных программах // Трансляция и модели программ. — 11овосибирск: ВЦ СО АН СССР, 1980. — С. 81—93. 44. Касьянов В. И. Полнота класса крупноблочных схем // Программные системы и вопросы эффективности использования ЭВМ. — Новосибирск, ВЦ СО АН СССР, 1982. — С. 81— 93. 45 Касьянов В. 11. Свободные интерпретации крупноблочных схем программ И Теоретиче- ские основы компиляции. — Новосибирск: НГУ, 1980. — С. 16—25. 46. Касьянов В. Н. Смешанные вычисления и оптимизация программ И Кибернетика. — 1980. —№2.- С. 51—54. 47. Касьянов В. Н. Теоретико-графовые задачи анализа управляющих графов транслируемых программ // Исследования по прикладной теории графов. — Новосибирск: Наука. Сиб. отд., 1986 —С. 9—25. 48. Касьянов В. Н. Трансформационный подход к конкретизации программ И Кибернетика. — 1989. —№6. —С. 28—32. 49. Касьянов В. I I. Эквивалентные преобразования кратных схем И Программирование. — 1982.—№2, —С. 3—8. 50. Касьянов В. Н Эквивалентные преобразования линейных участков программ // Трансля- ция и преобразования программ. — Новосибирск: ВЦ СО АН СССР, 1984. — С. 56—61. 51. Касьянов В. II.. Мирзуитова И. Л. Slicing: срезы программ и их применение.— Новоси- бирск, 2002. 52. Касьянов В. II., Поттосин И. В. Методы построения трансляторов.— Новосибирск: Наука, 1986,—344 с. 53. Касьянов В. Н., Трахтенброт М Б Анализ структур программ в глобальной оптимиза- ции // Труды Всесоюзного симпозиума по методам реализации новых алгоритмических языков. — Новосибирск: ВЦ СО АН СССР, 1975. — Ч. 1. •— С. 143—160. 54. Котов В. Е. Введение в теорию схем программ. — Новосибирск: Наука, 1978. 55. Котов В. Е., Сабельфельл В. К. Теория схем программ. — М.: Наука, 1991. 56 Кривицкий Н. А. Равносильные преобразования алгоритмов и программирование. — М.: Советское радио. 1970. 57. Кучеров Г. А. Системы подстановок термов.— Новосибирск, 1985.— 46 с.— (Препр./ АН СССР, Сиб. отд-ние; ВЦ; № 601). 58. Лавров С. С. Об экономии памяти в замкнутых операторных схемах // Жури, вычисл. ма- тематики и мат. физики. — 1961. — Т. 1, № 4. — С. 687—701. 59. Летичевский А А. Функциональная эквивалентность дискретных преобразователей I // Кибернетика. — 1969. — № 2. — С. 5—15. 60. Летичевский А. А. Функциональная эквивалентность дискретных преобразователей II // Кибернетика. — 1970. — № 2. — С. 14—28
910 Часть II. Применение графов и граф-моделей 61. Летичевский А. А. Функциональная эквивалентность дискретных преобразователей III// Кибернетика. — 1972. — № 1. —С. 1—4. 62. Мартынюк В. В. Выделение цепей в схемах алгоритмов // Журн. вычисл. математики и мат. физики.— 1961. — Т. 1, № 1. — С. 151—162. 63. Мартынюк В. В. Об анализе графа переходов для операторной схемы И Журн. вычисл. ма- тематики и мат. физики. — 1965. — Т. 5, № 2. — С. 298—310. 64. Мартынюк В. В. Об экономном распределении памяти // Журн. вычисл. математики и мат. физики. — 1962. —Т 2, № 3. 65. Никитин А. С. Об одном классе эквивалентных преобразований'операторных схем И Ки- бернетика. — 1977. —№ 5. 66. Подловченко Р. И. Недетерминированные схемы алгоритмов И Докл. АН СССР. — 1972. — Т. 207, № 4. — С. 789—792 67. Подловченко Р. И. Полная система подобных преобразований недетерминированных схем алгоритмов И Докл. АН СССР. — 1973. —Т. 212, № 1. — С. 64—66. 68. Поттосин И. В. К задаче чистки циклов// Цифровая вычислительная техника и програм- мирование. — М.: Советское радио, 1968. -— Выл. 4. — С. 18—36. 69 Поттосин И. В. К обоснованию алгоритмов оптимизации программ И Программирова- ние. — 1979. — № 3. — С. 3—13. 70. Поттосин И. В., Югринова О. В. Обоснование преобразования чистки циклов // Програм- мирование. — 1980. —№5. — С. 3—16. 71. Сабельфельд В. К. Критерий локальности преобразований операторных схем И Киберне- тика. — 1971. — № 5, —С. 59—62. 72. Тузов В. А. Проблемы разрешения для граф-схем с перестановочными операторами II // Кибернетика. — 1971. — № 5. — С. 23—32. 73 Тузов В. А. Эквивалентность логических схем с перестановочными операторами И Кибер- нетика. — 1970. — № 6. — С. 33—38. 74. Ферранте Дж., Оттенштейн К., Уоррен Дж. Граф программных зависимостей и его при- менение в оптимизации// Векторизация программ: теория, методы, реализация.— М.: Мир, 1991 С. 141—182. 75. Штаркман В. С. Блок экономии памяти //Проблемы кибернетики. -— М.: Физматгиз, 1958. 76. Янов Ю. И. О логических схемах алгори тмов И Проблемы кибернетики. — М.: Физматгиз. 1958. — Вып. 1, —С. 75—127. 77 Янов Ю. И. О локальных преобразованиях схем алгоритмов И Проблемы кибернетики. — М_. Наука, 1968. —Вып. 21. — С. 201 216. 78. Aho А. V., Sethi R., Ullman J. D. Compilers: Principles, Techniques and Tools. — Addison- Wesley, 1986. 79. Alpern В , Wegman M. N., Zadeck F. K. Detecting equality of values in programs H Conf Re- cord of the 12th Symp. on Principles of Programming Languages. — New York: ACM Press, 1985, —P. 281—290. 80. Bachmair L., Dershowitz N., Hsiang J. Ordering for equational proofs 11 Proc. IEEE Symp. on Logic in Comput. Sci — Cambridge, 1986. — P. 346—357. 81. Balance R. A., Maccabe A. B., Ottenstein K. J. The program dependence web: a representation supporting control-, data- and demand driven interpretation of languages// SIGPLAN Notices. — 1990. — Vol. 25, N 6. — P. 257—271.
Глава 11. Преобразование программ 911 82. Birkhofl'G. On the structure of abstract algebras// Proc. Cambridge Philos. Soc. — 1935.— Vol. 31. — P. 433—454. 83. Buchberger B. History and basic features of the critical-pair/compilation procedure // J. Sym- bolic Comput. — 1987. — Vol. 3. — P. 3—38. 84. Buchberger B., Loos R. Algebraic simplification // Computer Algebra— Symbolic and Alge- braic Comput. — Springer Verl., 1982. — P. 11—43. 85. Burke M. An interval-based approach to exhaustive and incremental interprocedural data-flow analysis// ACM Trans, on Programming Languages and Systems — 1990.— Vol. 12, N 3 P. 241—395. 86. Cooper K. Analyzing aliases of reference formal parameters // Conf. Record of the 12th Symp. on Principles of Programming Languages. — New York: ACM Press, 1985. — P. 281—290. 87. Cooper K., Kennedy K. Fast interprocedural alias analysis// Rroc. of the 16th ACM Symp. on Principles of Programming Languages. — New York: ACM Press, 1989. — P. 49—59. 88. Corbin J., Bidoit M. A rehabilitation of Robinson's unification algorithm/lnf. Proc. 83.— North-Holland, 1983. P 73—79. 89. Cytron R. K.. Ferrante J Efficiently computing <p-nodes on the fly // ACM Trans, on Program- ming Languages and Systems. — 1995. — Vol. 17, N 3. — P. 487—505. 90. Cytron R. K., Ferrante J., Rosen В. K., Wegman M. N., Zadeck F. K. Efficiently computing static single assignment form and the control dependence graph // ACM 1 rans. on Program- ming Languages and Systems — 1991. — Vol. 13, N 4. — P. 451—490. 91. Dershowitz N. Termination of linear rewriting systems И Leet. Notes Comput. Sci. — 1981. — Vol. 5, — P. 448—458. 92. Dershowitz N Termination of rewriting // J. Symbolic Comput. — 1987. — Vol. 3. — P. 69— 116. 93. Deutsch A. A storeless model of aliasing and its abstraction using finite representation of right- regular equivalence relations // Proc, of the IEEE Intern. Conf, on Computer Languages. ?— NJ: IEEE Computer Society Press, 1992. — P. 2—13. 94. Deutsch A Interprocedural may-alias analysis for pointers: beyond k-limiting // SIGPLAN No- tices. — 1994.—Vol. 29, N6. — P. 230—241. 95. Droster К. Towards executable specification using conditional axioms// Ibid.— 1984.— Vol. 166, —P. 85—96. 96. Emami M.. Rakech G., Hendren L. J. Context-sensitive interprocedural point-to analysis in the presence of function pointers И SIGPLAN Notices. — 1994. — Vol. 29, N 6. — P. 242—256. 97. Ferrante J., Ottenstein K. J., Warren J. D. The program dependence graph and its use in optimi- zation// ACM Trans, on Programming Languages and Systems.— 1987.— Vol. 9, N 3.— P 319—349. (Русский перевод см. [ФОУ91].) 98. GirkarM. В. Functional parallelism: theoretical foundations and implementations. — Univ, of Ill., CSRDRep. 1182,—Dec. 1991. 99. Girkar M. B., Polychronopoulos C. D. The HTG: an intermediate representation for programs based on control and data dependences. — Univ, of III., CSRD Rep 1046. — May 1991. 100. Guttag J. V., Kapur D., Musser D. R. On proving uniform termination and restricted termina- tion of rewriting systems//SIAM J. Comput. — 1983. — Vol. 12,N 1. — P. 189—214. 101. Harris T. J. A survey of PRAM simulation techniques // ACM Computer Surveys. — 1994. — Vol. 26, N 2. — P. 187—206
912 Часть II. Применение графов и граф-моделей 102 Hecht М. S. Flow analysis of computer programs. - - New York: Elsevier 1977. 103. Huet G. Confluent reductions: abstract properties and applications to term rewriting systems // J. ACM. — 1980. — Vol. 27, N 4. — P. 797—821. 104. Huet G. Resolution d'equations dans les languages d'ordre 1.2,...w: Ph.D. dis.— Univ. Paris VII, 1976. 105 Huet G., Oppen D. C. Equations and rewrite rules: a survey // Formal Languages Theory: Per- spectives and Open Problems. —New York: Acad. Press, 1980. 106. Jaffar J. Efficient unification over infinite terms// New Generation Comput.— 1984.— Vol. 2. —P. 123—171. 107 Jouannaud J. P., Kirchner H. Completion of a set of rules modulo a set of equations // SIAM J. Comput. — 1986 Vol. 15. — 1155—1194. 108. Kaplan D. M. Regular expressions and the equivalence of programs 11 J. Computer and Svstem Sci. — 1969. — Vol. 4, N 3. — P. 361—385. 109. Kaplan S. Condition rewrite rules// Theor. Comput. Sci.— 1984.— Vol. 33, N 2/3.— P. 139—174 110. Kapur D., MousserD., Narendran P., Stillman J. Semi-unification// Leet. Notes Comput. Sci. — 1988. — Vol. 338. — P. 435—454. 111. Kasyanov V. N. Annotated program transformations// Lecture Notes in Computer Science. — 1989. —Vol 405, —P. 171—180. 112. Kasyanov V. N. Basis for program optimization // Information processing 83. Proc. IFIP Con- gress 83. — Amsterdam, North—Holland, 1983. — P. 315—320. 113. Kasyanov V.N. Formal methods for program reusability// 15th IMACS World Congress on Scientific Computation, Modelling and Applied Mathematics. — Berlin Wissenschaft und Technik Verlag, 1997. — Vol. 4. — P. 761—766. 114. Kasyanov V. N. Loop cleaning // Information Processing Letters. — 1984. — Vol. 18, N 1. — P. 1^-6. 115. Kasyanov V. N. On completeness of mechanism of annotation-directives // Bull. Nov. Comput. Center. Senes: Comp. Science. — 1995. — Vol. 3. — P. 59—68. 116. Kasyanov V. N. Transformational approach to program concretization // Theoretical Computer Science. — 1991. — Vol. 90, N 1. — P. 37—46. 117. Kasyanov V. N., Lisitsyn I. A. Support tools for hierarchical information visualization 11 Hu- man-Computer Interaction: Communication, Cooperation and Application Design. — Law- rence Erlbaum Associates Publ., London, 1999 —Vol 2. — P. 117— 121 118. Kasyanov V. N., Pokrovsky S. B. Schematology in a multi-language optimizer // Lecture Notes in Comptuter Science. — 1977. — Vol. 53. — P. 315—323. 119. Kasyanov V. N., Trakhtenbrot M. B. Program structure analysis in a global optimization 11 Lec- ture Notes in Computer Science — 1977. — Vol. 47. — P. 90—104. 120. Knight K. Unification: a multidisciplinary survey// ACM Comput. Surveys.— 1989.— Vol. 21, N L —P. 93—124. 121. Knuth D., Bendix P. Simple word problems in universal algebras // Computational Problems in Abstract Algebra. —New York: Pergamon Press, 1970. —P. 263—297. 122 Krushkal J. B. Well-quasi-orderings, the tree theorem, and Vazsonyis's conjecture// Trans. Amer. Soc. — 1960. — Vol. 95. — P 210—225.
Гпава 11. Преобразование программ 913 123. Landi W., Ryder В. G. Safe approximate algorithm for interprocedural pointer aliasing// SIGPLAN Notices. — 1992. — Vol. 30, N 2 — P. 235—248. 124. Luckham D. C., ParkD. M., Paterson M. S. On formalized computer programs// J. Computer and System Sci. — 1970. — Vol. 4, N 3. — P. 220—249. 125. Martelli A., Montanary U. An efficient unification algorithm // ACM Trans on Program. Lan- guages and Systems. — 1982. — Vol. 4, N 2. — P. 258—282. 126. Matsumoto A., Han D. S., Tsuda T. Alias analysis of pointer in Pascal and Fortran90: Depend- ence analysis between pointer references // Acta Informatica. — 1996. — Vol. 33, Fasc. 2. — P. 99—130. 127. Metivier Y. About the rewriting systems produced by the Knuth-Bendix completion algo- rithm// Inf. Process. Let. — 1983. — Vol. 26, N 6. — P. 31—34. 128. Nararro M., Orejas F. On the equivalence of hierarchical and non-hierarchical rewriting on conditional term rewriting systems// Leet. Notes Comput. Sci.— 1984.— Vol. 174.— P. 74—85. 129. Nash-Williams C. St. J. A. On well-quasi-ordering finite trees// Proc. Cambridge Philos. Soc. — 1963. — Vol. 59. — P. 833—835. 130. Newmam M. H. A. On theories with a combinatorial definition of equivalence" 11 Annals of Math. — 1942. — Vol. 43. — P. 223—243. 131. Oeterson G., Stickel M. Complete sets of reductions for some equational theories// J. ACM. — Vol. 28, N 2. — P. 233—264. 132. Oyamaguchi M. The Cherch-Rosser property for ground term-rewriting systems is dicedable // Theor. Comput. Sci. — 1987. — Vol. 49, N 1. — P. 43—79. 133. Paterson M. S„ Wegman M. N. Linear unification// J. Comput. System Sci.— 1978.— Vol. 16, N 2. — P. 158—167. 134. Pingali K.., Beck M., Johnson R., Moudgill M., Stodghill R. Dependence flow graphs: An alge- braical approach to program dependencies. — Cornell Univ., Dept. Comp. Sci. Tech. Rep. 90—1152, — Sept. 1990 135. Robinson J. A. A machine-oriented logic based on the resolution principle// J. ACM.— 1965, —Vol. 12, N L — P. 23—41. 136. Ryder B. G. Constructing the call graph of a program // IEEE Trans. Soft. Eng. — 1979. — Vol. SE—5, N 3. — P. 216—226. 137. Schmitt P. H. A survey of rewrite systems // Leet. Notes Comput. Sci. — 1987. — Vol. 329. — P. 235—262. 138. Steensgaard B. Point-to analysis in almost linear time // Rec. of the 23th ACM Symp. on Prin- ciples of Programming Languages.— New York: ACM Press, 1996. — P. 32—41. 139. Thatcher J. W., Wagner E.G., Wright J. B. Data type specification: parametrization and the power of specification techniques// ACM Trans, on Program Languages Systems. — 1982. Vol. 4. —P. 711—732. 140. Uht A. K. A Theory of reduced and minimal procedural dependencies // IEEE Trans, on Com- puters. — 1991. — Vol. 40, N 6. — 681—692. 141. Venet A. Abstract cofibered domains: application to the alias analysis of untyped programs// Lecture Notes in Computer Science. — 1996. — Vol. 1145. — P. 366—382. 142. Wang S. S., Uht A. K. Program optimization with ideograph 11 Proc, of Intern. Conf, on Paral- lel Processing.— 1989. — P. 153—159.
ГЛАВА 12 Прочие граф-модели Данная глава посвящена таким важным графовым моделям, имеющим широкое при- менение в программировании, как диаграммы бинарных решений, графовые пред- ставления частично упорядоченных множеств, сети Петри и графы адресуемых данных. 12.1. Диаграммы бинарных решений Многие проблемы в таких областях, как проектирование цифровых систем, комбина- торная оптимизация, математическая логика и искусственный интеллект, могут быть сформулированы в терминах операций над небольшими конечными областями. По- средством введения бинарного кодирования элементов этих областей упомянутые проблемы могут быть сведены к операциям над булевыми значениями. Используя символьное представление булевых функций, мы можем выражать проблемы в обоб- щенной форме Решение такой обобщенной проблемы с помощью символьной обра- ботки булевых функций дает возможность разрешить большое количество конкрет- ных частных случаев. Следовательно, эффективный метод представления и обработки булевых функций может привести к решению большого класса сложных проблем. Упорядоченные бинарные диаграммы решений (Ordered Binary Decision Diagrams — OBDD) представляют булевы функции в виде ориентированных ациклических гра- фов. Они образуют каноническое представление, с помощью которого проверка та- ких функциональных характеристик, как выполнимость и эквивалентность, может быть произведена простым образом. Множество операций на булевых функциях мо- жет быть реализовано в виде графовых алгоритмов на OBDD-структурах данных. Используя упорядоченные бинарные диаграммы решений, мы можем решать про- блемы различных классов с помощью символьного анализа, если все возможные ва- риации параметров системы и технических условий можно закодировать с помощью булевых переменных. Данный раздел представляет собой обзор символьных булевых операций с упорядо- ченными бинарными диаграммами решений. Описываются OBDD-диаграммы и ал- горитмы их построения и обработки. Рассматриваются некоторые базовые техники
Гпава 12. Прочие граф-модели 915 для представления и обработки таких математических структур, как функции, множе- ства и отношения, с помощью символьных булевых операций. Эти техники проиллю- стрированы описанием некоторых приложений, использующих OBDD, а также рас- смотрены возможные направления дальнейших исследований. Хотя большая часть описанных приложений относится к области проектирования цифровых систем, по- хожие методы могут быть применены и в других областях. 12.1.1. Упорядоченные диаграммы бинарных решений и логические фрагменты Бинарная диаграмма решений (Binary Decision Diagrams или BDD) представляет бу- леву функцию в виде корневого ориентированного ациклического графа— дэга с одной выделенной вершиной, называемой корнем, которая не имеет предшествен- ников и из которой достижимы все его вершины. На рис. 12.1 представлен пример представления функции fixx, х2, х3). определяемой табл. 12.1, когда указанный граф является деревом. Каждая его нетерминальная (не висячая) вершина графа v помечена переменной ПЕР(у) и имеет две исходящих дуги к двум сыновьям: JlEB(v) (на рисунке показана пунктирной линией) в случае, когда переменной присваивается значение 0, и ПРАВ(у) (показана сплошной линией) в слу- чае, когда переменной присваивается значение 1. Каждая терминальная (висячая) вершина графа помечена либо 0, либо 1. Для заданного распределения значений ис- тинности логических переменных значение функции, реализованной диаграммой, определяется с помощью продвижения по пути от корня к терминальной вершине по ветвям, соответствующим присваиваемым переменным значениям. В качестве значе- ния функции берется метка найденной терминальной вершины. Дуги на данном ри- сунке упорядочены таким образом, что значения терминальных вершин (слева напра- во) соответствуют их вхождениям в таблицу истинности (сверху вниз). Рис. 12.1. Бинарная диаграмма решений булевой функции f, являющейся деревом. Пунктирные и сплошные дуги соответствуют случаям, когда значение разрешающей переменной равно 0 или 1, соответственно Таблица 12.1. Табличное задание функцииf х1 х2 Хз f ООО 0 0 1 ООО 0 1 1 1 1 0 1 0 1 1 0 0 1 1 1 0 0 0 1 0 1 0 1
916 Часть II. Применение графов и граф-моделей В случае упорядоченной бинарной диаграммы решений (OBDD) рассматривается некоторый линейный порядок < на множество переменных и требуется, чтобы для любой вершины и и любого ее преемника v, не являющегося терминальной верши- ной, соответствующие им переменные были упорядочены: ПЕР(и) < FlEP(v). К при- меру, в дереве решений (см. рис. 12.1) переменные упорядочены следующим обра- зом: Х| < Хг < х3. Теоретически порядок переменных может быть выбран произвольно — алгоритмы будут работать корректно при любом выборе порядка. Но на практике выбор подхо- дящего упорядочения является критичным для эффективности символьной обра- ботки. Определяются три правила преобразования описанных графов, не изменяющих зна- чение представляемой функции. Удаление дублирующих терминальных переменных. Удаляются все терминальные вершины с заданной меткой, кроме одной, а все дуги, ведущие к удаленным верши- нам, перенаправляются в оставшуюся вершину. Удаление дублирующих нетерминальных вершин. Если для нетерминальных вер- шин и и v выполняются следующие условия: ПЕР(м) = ПЕР(г), ЛЕВ(м) = JIEB(v) и ПРАВ(гг) = ПРАВ(т), то одна из этих вершин удаляется, а все дуги, входящие в нее, перенаправляются во вторую вершину. Удаление избыточных проверок Если для нетерминальной вершины v верно ЛЕВ(г) = FIPAB(v), то v удаляется, а все дуги, входящие в нее, перенаправляются в JIEB(v). Начиная с любой бинарной диаграммы решений, обладающей порядком, можно пы- таться сократить ее размер путем последовательного применения правил преобразо- вания. Термин OBDD используется для обозначения максимально приведенного гра- фа, обладающего некоторым фиксированным порядком на множестве переменных. Пример на рис. 12.2 иллюстрирует процесс приведения дерева решений, представ- ленного на рис. 12.1, к OBDD. Применение первого правила преобразования сокра- щает количество терминальных вершин с 8 до 2. Применение второго правила удаля- ет две вершины с переменной х3 и дуги к терминальным вершинам с метками О (ЛЕВ) и 1 (ПРАВ). Применение третьего правила удаляет две вершины: одну с переменной х3 и одну с переменной х3. В общем случае правила преобразования должны приме- няться неоднократно, поскольку каждое применение преобразования может привести к появлению новых возможностей для других преобразований. Представление функции в виде OBDD является универсальным и каноническим. А. Любая булева функция при любом заданном порядке на переменных имеет OBDD- представление. Б. Для любого заданного порядка на переменных две упорядоченных бинарных диа- граммы решений одной и той же функции изоморфны. Из этого вытекают несколько важных следствий. Легко может быть проверена функ- циональная эквивалентность. Функция является выполнимой в том и только том слу- чае, когда ее OBDD-представление не сводится к одиночной терминальной вершине
Гпава 12. Прочие граф-модели 917 с меткой 0. Любая тавтологическая функция должна иметь терминальную вершину с меткой 1 в качестве своего OBDD-представления. Если функция не зависит от пе- ременной х, то ее OBDD-представление не может иметь вершин, помеченных х. Та- ким образом, как только построены представления функций в виде OBDD, многие их характеристики становятся легко проверяемыми. Рис. 12.2. Приведение дерева решений к OBDD: а — удаление дублирующих терминальных переменных, б — удаление дублирующих нетерминальных переменных, е — удаление избыточных проверок Как демонстрируют рис. 12.1 и 12.2, можно строить OBDD-представление для функ- ции, заданной таблично, построив ее, а затем сократив ее дерево решений. Однако этот подход является практичным только для функций с небольшим количеством пе- ременных, поскольку и таблица истинности, и дерево решений имеют экспоненци- альный по отношению к числу переменных размер. Поэтому OBDD обычно строятся при помощи "символьного выполнения" логического выражения или сети логических элементов с применением операции APPLY (см. разд 12 1.2). Форма и размер OBDD, представляющей функцию, зависит от способа упорядочения переменных. На рис. 12.3 приведен пример двух OBDD-представлений функции, за- данной булевым выражением + а2*^2 + а3*Ь3, где "*" обозначает операцию AND, а "+" — операцию OR. Для примера на рис. 12.3, а был задан следующий поря-
918 Часть II. Применение графов и граф-моделей док переменных: а, < Ьх < «2 < th < аз < Ь3, тогда как на рис. 12.3, б порядок был та- ким: Я] < а2 < аз < bi < b2 < Ь3. Рис. 12.3. OBDD-представления одной и той же функции для двух различных способов упорядочения переменных: a — ai < bi < аз < Ьг < аз < Ьз б — a-i < а2 < аз < £>1 < Ь2 < Ьз Можно обобщить эту функцию следующим образом: ai*bt + я2*62 + — + а„*Ьп. Обоб- щение первого способа упорядочения переменных до < Ь\ < ... < а„ < Ь„ дает OBDD-представление с количеством нетерминальных вершин, равным 2и. Обобще- ние второго способа до < ... а„ < 6, < ... < Ьп, с другой стороны, дает в результате OBDD-представление с 2(2"— 1) числом нетерминальных вершин. Для больших зна- чений п разница между линейным возрастанием первого представления и экспонен- циальным ростом второго будет иметь существенное влияние на объем требуемой памяти и эффективность алгоритма обработки. Исследуя структуру двух графов на рис. 12.3, мы видим, что в первом случае (рис. 12.3, а) переменные объединены в пары в соответствии с их вхождением в буле- во выражение a,*6i + a2*b2 + а3*Ь3. Таким образом, для любого второго уровня в графе имеются только два возможных пункта назначения исходящих ветвей: одна ведет к терминальной вершине, помеченной 1, в случае, когда соответствующее про- изведение дает 1; вторая ведет к следующему уровню в случае, если все произведения переменных до этого момента были равны нулю. С другой стороны, все три уровня во втором случае (рис. 12.3, б) образуют полное бинарное дерево, описывающее все возможные присваивания переменным а,. В общем случае при каждом присваивании переменным а значение функции единственным образом зависит от присваивания переменным />,. Поскольку мы обобщаем эту функцию и порядок на более чем 2п переменных, первые п уровней OBDD образуют полное бинарное дерево.
Гпава 12. Прочие граф-модели 919 Большинство приложений, использующих OBDD, выбирают некоторый порядок пе- ременных с самого начала и строят все графы в соответствии с этим порядком. По- скольку проблема нахождения оптимального упорядочения переменных для OBDD является TVP-трудной, порядок, как правило, выбирается либо вручную, либо с по- мощью эвристического анализа представляемой системы Например, были разрабо- таны некоторые эвристические методы, которые, получив на входе сеть логических элементов, обычно выводят хороший способ упорядочения переменных, представ- ляющих первичные входные данные. Другие методы были разработаны для анализа последовательных систем. Заметим, что упомянутые эвристики не обязаны находить оптимальное упорядочение — выбор порядка не влияет на корректность результатов. Как только обнаружен порядок, не приводящий к экспоненциальному росту, опера- ции на OBDD показывают приемлемую эффективность. OBDD представляет собой практичный подход к символьной булевой обработке только в том случае, когда размер графа остается значительно меньше экспоненци- ального относительно количества переменных. Как показано в рассмотренном при- мере, некоторые функции чувствительны к упорядочению переменных, но остаются вполне компактными, если выбран хороший порядок. Имеется достаточный эмпири- ческий опыт, чтобы утверждать, что многие функции из реальных приложений могут быть эффективно представлены в виде OBDD. Одним из способов более полно пред- ставить сильные и слабые стороны OBDD-представления может быть вывод нижних и верхних границ для важнейших классов булевых функций. В табл. 12.2 сведены воедино асимптотические оценки степени возрастания для не- скольких классов булевых функций и их чувствительность к упорядочению перемен- ных. Симметричные функции, у которых значение функции зависит только от коли- чества аргументов, равных 1, нечувствительны к порядку переменных. За исключени- ем тривиального случая константных функций, графы симметричных функций попадают в промежуток между линейными (например, четность) и квадратичными (например, не менее половины входных данных равны 1). Таблица 12.2. Сложность OBDD-представления для широко распространенных классов функций Класс функций Сложность Лучший случай Худший случай Симметричные Линейная Квадратичная Целочисленное сложение (любой бит) Линейная Экспоненциальная Целочисленное умножение (средние биты) Экспоненциальная Экспоненциальная Мы можем рассматривать каждое выходное значение «-битового сумматора как булеву функцию на переменных п0, «ь —, ь представляющих один операнд, и Ьо,
920 Часть II. Применение графов и граф-моделей bi,..., b„ !, представляющих второй операнд. Функция для любого бита имеет OBDD- представление линейной сложности для порядка «0 < < а} < Ь\ < ... < а„ ] < Ь„ , и экспоненциальной сложности для порядка а0< at < ... < а„ t < b0< bt <... < b„ j. Фактически представление таких функций похоже на представление функции, изо- браженной на рис. 12.3. Булевы функции, представляющие целочисленное умножение, являют собой особен- но сложный случай для OBDD. В. Вне зависимости от способа упорядочения булева функция, представляющая лю- бое из двух средних выходных значений п-битного умножителя, имеет экспоненци- альное OBDD-представление. Верхние границы для других классов булевых функций могут быть выведены на ос- нове структурных свойств их логических сетей. Рассмотрим сеть с п первичными входными значениями и одним первичным выходным значением, состоящую из т "логических блоков". Каждый блок может иметь несколько входов и выходов. Пер- вичные данные представлены "исходными" блоками без входа и с одним выходом. В качестве примера на рис. 12.4 приведена сеть, дающая в качестве выходного значе- ния самый важный бит суммы «-битного сумматора. Эта сеть состоит из цепи пере- носа, последнее значение которой вычисляется из с„ |. Блоки, помеченные "2/3", вы- числяют функцию MAJORITY, которая дает на выходе 1, если по меньшей мере два входных значения равны 1. Выходное значение вычисляется как EXCLUSIVE-OR самых важных битов входных значений и с„ ь Рис. 12.4. Линейное расположение цепи, вычисляющей самый главный бит целочисленного сложения Определим линейное расположение сети как нумерацию блоков от 1 до и? таким об- разом, что блок, вычисляющий выходное значение, пронумерован последним. Опре- делим прямое поперечное сечение в блоке Z как общее количество проводов, ведущих из выхода блока j (j < I) ко входу блока к (/ < к). Определим прямое поперечное сече- ние цепи Wj (относительно расположения) как максимальное прямое поперечное се- чение среди всех блоков. Как видно на рис. 12.4, прямое поперечное сечение нашей цепи сумматора равно 3 (обозначено пунктирной линией). Подобным же образом определим обратное поперечное сечение в блоке i как общее количество проводов, ведущих из выхода блока j (J < I) ко входу блока к (/ < к). В тех расположениях, где блоки упорядочены топологически, обратное поперечное сечение равно нулю. На рис. 12.4 мы имеем именно такую картину. Определим прямое поперечное сечение цепи wr (относительно расположения) как максимальное прямое поперечное сечение среди всех блоков. Можно показать, что существует OBDD-представление функции
Глава 12. Прочие граф-модели 921 цепи с не более чем л2 ' вершинами. Более того, нахождение расположения с низ- кими поперечными сечениями означает нахождение хорошего способа упорядочения переменных функции — таким порядком будет инверсия порядка соответствующих исходных блоков в их расположении. С помощью сетевых реализаций можно найти подходящие границы для различных булевых функций. Например, функции, имеющие реализацию с постоянным прямым поперечным сечением и нулевым обратным поперечным сечением (такие, как цепь сумматора на рис. 12.4), имеют линейное OBDD-представление. Симметричная функция от и переменных может быть реализована в виде цепи с прямым попереч- ным сечением 2 + log и и обратным поперечным сечением 0. Эта цепь состоит из се- рии каскадов, вычисляющих общее количество входных значений, равных 1, кодируя их в виде [log2 побитного двоичного числа. Эта реализация приводит к квадратичной верхней границе OBDD-представления, указанной в табл. 12.2. Рис. 12.5. Линейное расположение кольцевой цепи для Within-K. Пунктирной линией показано прямое поперечное сечение 2 + [log? К] и обратное поперечное сечение [logz К] На рис. 12.5 изображено применение этого результата к цепи с ненулевым обратным поперечным сечением. Эта цепь представляет общую реализацию функции Within-K, где К — некоторая константа, такая, что 0 < К < и. Для набора входных значений х0, хь ..., хп । функция выдает значение 1 в случае, когда имеются входные значения xt и х,', равные 1, причем i’= i + j mod л для некоторого значения j, 0 <J < К. Как показано на рис. 12.5, эта функция может быть вычислена с помощью серии блоков, располо- женных в виде кольца, где каждый блок В, выдает на выходе 1-битное значение s, и A-битное целочисленное значение L„ где к = [log2AQ: fl, если х = 1 и L, , * 0, s, = ( (s, ! —в противном случае, К-1, если X] = 1, £, = Д ] -1, если X] = 0 и Д_] >0, 0— в противном случае. В данной реализации каждый сигнал L, кодирует количество оставшихся позиций, с которыми может составить пару самое последнее входное значение 1, в то время как каждый сигнал s, показывает, встретилась ли уже пара входных значений, рав- ных 1, внутри дистанции К. Чтобы удовлетворять условию близости модулей, выход
922 Часть II. Применение графов и граф-моделей Li} последнего каскада направляется на вход начального каскада Заметим, что, хотя эта цепь имеет циклическую структуру, ее выходное значение однозначно определя- ется входными значениями. Как отмечено пунктирной линией, эта кольцевая струк- тура может быть "сплющена" до линейного расположения с прямым поперечным сечением к +1 и обратным поперечным сечением к Эта конструкция дает верхнюю границу OBDD-представления, равную (8Х 4К)п. Для константных значений К размер OBDD будет линейным, хотя постоянный коэффициент будет быстро возрастать с ростом К. Существует обобщение этой техники до древовидного расположения, в котором сеть организована в виде дерева логических блоков с коэффициентом ветв- ления b и первичным выходным значением, производимым корневым блоком. При таком расположении прямое поперечное сечение соответствует количеству проводов, направленных к корню (для обратного сечения — соответственно, из корня). Эта кон- струкция дает верхнюю границу размера OBDD-представления п\2ь пь~} ]”/2 . Верх- няя граница для линейного расположения получается подстановкой b = 1 в эту фор- мулу. Заметим, что для константных значений b, Wj и wr размер OBDD будет полино- миальным относительно п. Эти оценки верхней границы дают некоторое представление о том, какое количество функций, встречающихся в приложениях в области логического проектирования, имеют эффективные OBDD-представления. Они также позволяют предложить стра- тегию обнаружения хороших способов упорядочения переменных с помощью нахож- дения сетевых реализаций с низкими поперечными сечениями. Результаты, получен- ные для этой формы представления булевых функций, могут оказаться полезными при оценке потенциала OBDD-представления в других областях применения. Есть целый ряд различных усовершенствований базовой структуры OBDD, дающих значительную экономию при выделении памяти-— как правило, наиболее критичного ресурса при определении сложности решаемых проблем. (Приложения, требующие генерации более чем миллиона вершин OBDD, трудно исполнить на обычных рабо- чих станциях.) К ним относятся, например, использование единственного многокор- невого графа для представления всех требуемых функций, снабжение дуг метками для обозначения булева вычитания и обобщение понятия областей с конечным чис- лом состояний. 12.1.2. Конструирование и манипуляция Введем систему обозначений для описания операций на булевых функциях. Мы бу- дем использовать стандартные операции булевой алгебры: "+" для OR, " • " для AND, "Ф" для EXCLUSIVE-OR и верхний подчерк для NOT. Дополнительно мы будем ис- пользовать символ Ф , обозначающий дополнение к операции EXCLUSIVE-OR (на- зываемую EXCLUSIVE-NOR). Мы также используем понятия суммы "Z" и произве- дения "П", подразумевая под ними булеву сумму OR и произведение AND. Заметим, что эти операции определяются над функциями, так же как и над булевыми значения- ми 0 и 1. К примеру, если/и g— функции над некоторым множеством переменных, то/+ g также является функцией (например, Л) над этими же переменными. Для не- которого присваивания значениям переменных a, h(a') выдает значение 1 в том и
Гпава 12. Прочие граф-модели 923 только том случае, когда либо/а), либо g(a) выдает значение 1. Константные функции, значение которых равно 1 или 0 для любых присваиваний, обозначаются как 1 и 0, соответственно. Функция, которая получается, когда некоторому аргументу х функции f присваивает- ся константное значение к (0 либо 1), называется рестрикцией функции/(иногда ее также называют "кофактором"/) и обозначается/|л<_*. Если даны две рестрикции функции относительно одной переменной, функция может быть реконструирована следующим образом:/= х /| А<_0 + х -/|x<_i. Это тождество часто называют Шенно- новым разложением f по переменной х, хотя впервые оно было упомянуто Булем. Многие другие полезные операции могут быть определены в терминах алгебраи- ческих операций и операции рестрикции. Операция композиции, при которой функция g заменяет переменную х функции / задается следующим тождеством: /1.«-g — 8 '/1 х«~0 & '/1«-1- Операция квантификации переменной, при которой некоторая переменная х экзи- стенциально или универсально оценивается относительно функции/ задается тожде- ствами Эх/=/|А<_о +/L«-i и Vx/=/|.«_о • /| д<-|. Некоторые исследователи предпочи- тают называть эти операции сглаживанием (экзистенциальная квантификация) и кон- сенсусом (универсальная квантификация), чтобы подчеркнуть тот факт, что они являются операциями над булевыми функциями, а не над истинностными значе- ниями. Большое количество символьных операций над булевыми функциями может быть реализовано в виде графовых алгоритмов, применяемых к упорядоченным бинарным диаграммам решений. Эти алгоритмы обладают важным свойством замыкания — если аргументы функции представляют собой OBDD с некоторым порядком, то ре- зультатом функции будет OBDD с тем же порядком. Следовательно, мы можем реа- лизовать сложную обработку с помощью последовательности простых манипуляций, всегда работая с OBDD с привычным порядком. Пользователи могут рассматривать библиотеку подпрограмм обработки бинарных диаграмм решений как реализацию абстрактного типа данных — булевой функции. За исключением выбора способа упо- рядочения переменных, все операции реализуются полностью автоматически. Поль- зователю нет необходимости вдаваться в детали представления или реализации. Операция APPLY Операция APPLY генерирует булевы функции путем применения алгебраических операций к другим функциям. Если в качестве аргументов заданы функции / и g и бинарный булев оператор <ор> (например, AND или OR), то функция APPLY выдает в результате функцию / <ор> g. Эта операция является важнейшей для символьной булевой обработки. С ее помощью мы можем находить дополнение функции / вы- числяя /Ф 1. Пусть даны функции /и g и состояние безразличности, выраженное функцией d (т. е. <7( х ) равно 1 для тех присваиваний переменным х, для которых значения функции не важны), тогда мы можем проверить, являются ли/и g эквива- лентными для всех "небезразличных" состояний, вычисляя значение (f Ф g) + d и проверяя, равен ли результат функции значению 1. Мы также можем построить
924 Часть II. Применение графов и граф-моделей OBDD-представление выходных функций сети комбинационно-логических элементов путем 'символической интерпретации" сети. Это производится следующим образом. Вначале мы представляем функцию на каждом первичном входе в виде OBDD, со- стоящего из проверки одной переменной. Затем в порядке, определяемом структурой сети, мы применяем операцию APPLY для построения OBDD-представления каждого выходного элемента в соответствии с операцией, выполняемой элементом, и OBDD, построенными для входных значений этого элемента. Алгоритм APPLY производит обход графов аргументов в глубину, поддерживая две хэш-таблицы: одну — для улучшения производительности вычисления, вторую —- для построения максимально приведенного графа. Заметим, что в отличие от более ранних алгоритмов, которым требовался отдельный шаг для приведения сокращаемо- го графа к канонической форме, описанный алгоритм строит приведенную форму сразу. Чтобы проиллюстрировать эту реализацию операции, мы рассмотрим процесс применения операции "+" к функциям У(п, b, с, d) = (а + Ь) с + d и g(o, b,c,d} = = (a c ) + d, OBDD-представление которых показано на рис. 12.6. Рис. 12.6. Аргументы операции APPLY. Вершины помечены для идентификации их в следе исполнения Реализация операции APPLY опирается на то, что алгебраические операции связаны Шенноновым разложением по любой переменной х: /<ор> g = х • (/1 А<_0 <ор> g | А4_о) + х (/'| А<_, <ор> g I «-1) (12.1) Заметим, что для функции f, представленной диаграммой с корневой вершиной rfi рестрикция относительно переменной х, такой, что х < ПЕР(/у), может быть вычисле- на следующим простым способом: /у, если х < ПЕР(/у ), ЛЕВ(уу), еслих=ПЕР(/у)и£>=0, ПРАВ(лу ), если х=ПЕ Р(ду ) и b=1.
Гпава 12. Прочие граф-модели 925 То есть рестрикция представлена либо тем же самым графом, либо одним из подгра- фов корневой вершины. Равенство 12.1 образует базис для рекурсивной процедуры вычисления OBDD- представления f <ор> g. Структура рекурсивного вычисления для нашего примера представлена на рис. 12.7. Заметим, что каждый шаг вычисления идентифицируется вершиной каждого из графов-аргументов. Предположим, что функции fug представ- лены OBDD-диаграммами с корневыми вершинами /у и rg, соответственно. В случае, когда и туи rg являются терминальными вершинами, рекурсия завершается, возвращая подходящим образом помеченную терминальную вершину. В нашем примере это происходит при вычислении Л4, и А5, В4. В противном случае будем считать х рас- щепляющей переменной, определяя ее как минимум из переменных ПЕР(/у) и ПЕР(гх). OBDD-диаграммы для функций f\ х<_0 <ор> g |Л<_0 и /|А<_| <ор> gL<-i строятся путем рекурсивного выполнения рестрикций fug для значения 0 (обозначенных пунктир- ными линиями на рис. 12.7) и для значения 1 (обозначенных сплошными линиями). В нашем примере начальное вычисление для вершин At,Bi вызывает рекурсивное вычисление для вершин А2, В2 и А6, В5. Рис. 12.7. След исполнения операции APPLY с операцией "+". Каждый шаг аыполнения имеет в качестве операндов вершину из каждого графа-аргумента Чтобы более эффективно реализовать операцию APPLY, можно ввести два усовер- шенствования в описанную процедуру вычисления OBDD-представления f <ор> g. Во-первых, если встречается условие, в котором один из аргументов является терми- нальной вершиной, представляющей "доминантное" значение для операции <ор> (например, 1 для OR или 0 для AND), то можно остановить рекурсию и вернуть под- ходящим образом помеченную терминальную вершину. В нашем примере это проис- ходит при вычислении для А5, В2 и А3, Вц.
926 Часть II. Применение графов и граф-моделей Во-вторых, можно избегать любых множественных рекурсивных вызовов одной и той же пары аргументов путем поддержки хэш-таблицы, в которой каждая запись в каче- стве ключа содержит пару вершин двух графов-аргументов, а в качестве элемента данных — вершину генерируемого графа. В начале выполнения для аргументов и и v проверяется наличие записи с ключом <и, v> в хэш-таблице. Если такая запись обна- ружена, возвращается элемент данных этой записи, что позволяет прекратить даль- нейшую рекурсию. Если записи не найдено, производятся описанные действия по созданию новой записи перед возвратом результата. В нашем примере с помощью этого усовершенствования мы избегаем множественного исполнения для аргументов А5, В2 и Л3, Вц. Заметим, что при использовании указанного усовершенствования структура вычисления представлена ориентированным ациклическим графом, а не более привычной для рекурсивных процедур древовидной структурой. Рис. 12.8. Генерация результата для операции APPLY: а — структура рекурсивных вызовов по своей природе определяет неприведенный граф, б— с помощью применения правил сокращения в конце каждого рекурсивного вызоаа сразу же строится приведенный граф Каждый шаг вычисления возвращает в качестве результата вершину генерируемого графа. Структура рекурсивного выполнения по своей природе определяет неприве- денный граф, в котором каждый шаг вычисления задает вершину, помеченную рас- щепляющей переменной и имеющую в качестве потомков результаты рекурсивных вызовов. Такой граф для нашего примера показан на рис. 12.8. Чтобы сразу же гене- рировать приведенный граф, на каждом шаге выполнения мы пытаемся "уклониться" от создания новой вершины с помощью применения тестов, соответствующих опи- санным в данном разделе правилам преобразования. Предположим, что шаг выпол- нения содержит расщепляющую переменную х, и рекурсивные вычисления возвра- щают вершины v0 и V]. Вначале мы проверяем, выполняется ли условие v0 = vb и если выполняется, то мы возвращаем эту вершину как результат процедуры. Затем мы проверяем, не содержит ли уже сгенерированный граф какую-нибудь вершину v, та- кую, что ПЕР(г) = х, JIEB(v) = v0 и ПРАВ(у) = vb Эта проверка сопровождается под-
Гпава 12. Прочие граф-модели 927 держкой хэш-таблицы, содержащей запись для каждой нетерминальной вершины v в сгенерированном файле с ключом <ПЕР(г), ПРАВ(г), JIEB(v)>. Если искомая верши- на найдена, она возвращается как результат процедуры. В противном случае вершина добавляется в граф, ее запись добавляется в хэш-таблицу и вершина возвращается как результат процедуры. Подобным же образом в хэш-таблице оказываются терминаль- ные вершины, их ключами являются метки. Новая терминальная вершина генериру- ется только в том случае, если не имеется вершины с нужной меткой. В нашем при- мере этот процесс не создает вершины, изображенные пунктиром (см. рис. 12.8, а). Напротив, граф (см. рис. 12.8, б) генерируется непосредственно. Заметим, что этот граф представляет функцию a + b*c + d, которая и является результатом применения операции OR к двум функциям-аргументам. Использование таблицы для устранения множественного исполнения данной пары вершин ограничивает временную сложность алгоритма APPLY и одновременно зада- ет границу размера результата. А именно, пусть функции fug представлены OBDD- диаграммами с количеством вершин иу и mg, соответственно. Тогда может быть не более чем nij mg уникальных аргументов для вычисления, и каждое вычисление до- бавляет не более одной вершины к генерируемому результату. Имея хорошую реали- зацию хэш-таблицы, мы можем провести каждый шаг вычисления в среднем за кон- стантное время. Таким образом, и сложность алгоритма, и размер генерируемого ре- зультирующего графа должны оцениваться как О(пуггу). Операция RESTRICT Вычисление рестрикции функции, представленной любым видом бинарной диаграм- мы решений, довольно просто. Чтобы выполнить рестрикцию переменной х до значе- ния к, мы перенаправим любую дугу, ведущую к вершине v, для которой ПЕР(г) = х, либо в JlEB(v) для к=0, либо в ПРАВ(у) для к= 1. На рис. 12.9 представлена рест- рикция переменной Ь в функции b*c + a*b * с до значения 1. Исходная функция за- дана OBDD на рис. 12.9, а. После перенаправления дуг вершина b исключается, что показано на рис. 12.9, б, а затем осуществляется приведение (рис. 12.9, в). Как видно из этого примера, прямая реализация техники рестрикции может дать в итоге непри- веденный граф. Взамен этого вначале производится обход исходного графа в глуби- ну. Каждый рекурсивный вызов имеет своим аргументом вершину в исходном графе и возвращает в виде результата вершину генерируемого графа. Чтобы гарантировать, что генерируемый граф является приведенным, процедура поддерживает хэш- таблицу, содержащую запись для каждой вершины генерируемого графа, применяя те же правила сокращения, что и при операции APPLY. В нашем примере результат мо- жет быть OBDD-представлением функции с (см. рис. 12.9, в). Вычисление рестрикции функции / OBDD-представление которой имеет иу вершин, содержит не более чем т} рекурсивных вызовов, каждый из которых генерирует не более одной вершины результирующего графа. Имея хорошую реализацию хэш- таблицы, каждый шаг рекурсии требует в среднем константного времени. Таким об- разом, и сложность алгоритма, и размер генерируемого результирующего графа мож- но оценить как О(/иД
928 Часть II. Применение графов и граф-моделей Рис. 12.9. Пример операции RESTRICT: а — исходное представление функции, б— рестрикция переменной b до значения 1 приводит к исключению вершин, помеченных b е — приведенный граф Производные операции Как было описано, значительное количество операций над булевыми функциями мо- жет быть выражено в терминах алгебраических операций и операции рестрикции. Выполнение APPLY и RESTRICT дают способ реализации этих операций. Далее, для каждой из этих операций ее сложность и размер генерируемого графа ограничены некоторой полиномиальной функцией относительно функций-аргументов. Обозначим размер OBDD-представления функции f как mf Пусть даны функции/и g и "состоя- ния безразличности", выраженные функцией d, тогда мы можем вычислить эквива- лентность /и g для "небезразличных" состояний за время О^пут^т^). Мы можем вы- числить композицию функций/и g с двумя рестрикциями и тремя вызовами APPLY. Этот подход дает временную сложность Реализуя все вычисление за один проход, можно сократить эту оценку до Наконец, можно провести кванти- фикацию переменной функции f за время О(пу). Характеристики производительности Использование OBDD для решения проблемы требует выражения задания в виде се- рии операций на булевых функциях, подобных описанным. Как мы видели, все эти операции могут быть реализованы с помощью алгоритмов, полиномиальных по сложности относительно размера диаграмм, представляющих аргументы. В результа- те основанные на OBDD символьные булевы операции имеют два преимущества по сравнению с другими общепринятыми подходами. Во-первых, до тех пор, пока размеры графов остаются приемлемыми, все вычисление в целом оказывается контролируемым. Во-вторых, хотя размеры графов могут возрастать с каждой успешной операцией, любая отдельная операция имеет разумную производительность в худшем случае.
Гпава 12. Прочие граф-модели 929 Напротив, многие другие представления булевых функций не обладают этим свойст- вом "постепенного снижения производительности". Например, справедливо следую- щее свойство. А. Даже если функция имеет умеренно компактное представление суммы произве- дений, ее дополнение может быть экспоненциального размера. Технология реализации С точки зрения реализации, основанные на OBDD символьные операции имеют ха- рактеристики, отличающие их от многих других вычислительных задач. Во время вычисления конструируются и уничтожаются тысячи графов, содержащие тысячи вершин каждый. Информация представлена при использовании OBDD-представлений скорее самой их структурой, чем ассоциированными с ними данными, и в силу этого к каждой отдельной вершине прилагаются очень небольшие вычислительные дейст- вия. Таким образом, вычисление носит высоко динамичный характер, не позволяю- щий делать предварительных предположений об обращениях к памяти. В настоящее время наиболее успешные варианты реализации были получены на рабочих станциях с большой физической памятью, на которых уделялось много внимания программи- рованию процедур управления памятью. Чтобы достичь максимальной производительности, было бы желательно использо- вать потенциал конвейерных и параллельных компьютеров. В задачах символьного анализа параллелизм может существовать на макроуровне, когда многие операции могут быть исполнены одновременно, и на микроуровне, когда многие вершины внутри заданного OBDD могут быть обработаны одновременно. В сравнении с дру- гими задачами, которые были успешно реализованы на векторных и параллельных компьютерах, обработка с использованием OBDD требует заметно большей комму- никации и синхронизации между вычисляющими элементами и заметно меньших локальных вычислений. Эта задача пока остается вызовом для разработчиков архи- тектур параллельных компьютеров, программных моделей и языков программирова- ния. Тем не менее некоторые из первых попыток оказались многообещающими. Ис- следователи успешно использовали векторную обработку и показали хорошие ре- зультаты при исполнении на мультипроцессорах с разделенной памятью. Оба подхода используют параллелизм на микроуровне с помощью реализации операции APPLY в виде обхода графов-аргументов в ширину, в противоположность общепри- нятому для большинства других реализаций обходу в глубину. 12.1.3. Представление математических объектов Некоторые приложения, чаще всего в области разработки цифровых систем связи, требуют прямой реализации и обработки булевых функций. Однако в общем случае мощность символьной булевой обработки состоит в способности бинарных значений и булевых операций представлять и воплощать разнообразные области математики. В табл. 12.3 приводятся примеры некоторых разделов математики, в которых объек- ты могут быть представлены, обработаны и проанализированы с помощью символь- ных булевых операций, т. к. лежащие в их основе области являются конечными. Пре- 30 Зак. 202
930 Часть II. Применение графов и граф-моделей доставляя унифицированную структуру для различных математических систем, сим- вольная булева обработка дает возможность решать не только проблемы в отдельных областях, но и проблемы, затрагивающие различные области математики. Например, разработаны программы для анализа последовательного поведения цифровых схем, которые включают операции над всеми перечисленными в табл. 12.3 областями. Тре- буемые свойства системы выражаются в виде логических формул. Поведение систе- мы задается функциями следующего состояния схемы. Анализатор вычисляет множе- ства состояний, имеющих определенные свойства. Структура переходов в системе конечного автомата представлена в виде отношения. Во время исполнения анализа- тор может быстро перемещаться между представлениями, используя только OBDD как базисную структуру данных. Более того, свойство каноничности OBDD позволяет с легкостью распознавать такие условия, как сходимость, и определять, существует ли решение заданной проблемы. Таблица 12.3. Примеры систем, которые могут быть представлены булевыми функциями Класс Типичные операции Типичные тесты Логика А, V, V, Э Выполнимость, импликация Конечные области Проблемно-завиашые Эквивалентность Функции Аппликация, композиция Эквивалентность Множества U, - Подмножество Отношения Композиция, замыкание Симметричность, транзитивность Ключом к использованию возможностей символьной булевой обработки является выражение исходной проблемы в форме, в которой все объекты представлены буле- выми функциями. В оставшейся части данной главы мы опишем некоторые стандарт- ные техники, которые были разработаны для этой цели. Имея достаточный опыт и практику, можно представить в таком виде удивительно широкий класс проблем. Ма- тематические основы для этого представления были разработаны уже давно. Ни одна из рассматриваемых техник не опирается на особенности OBDD-представления — они могут быть реализованы для любого из множества представлений. Разработка OBDD-представления просто расширила спектр проблем, которые могут быть разре- шены практически. Однако тем самым она усилила мотивацию к представлению раз- личных проблем в терминах символьных булевых операций. Кодирование конечных областей Рассмотрим конечное множество элементов А, I л| = N. Мы можем кодировать эле- мент из И с помощью вектора из п бинарных значений, где « = Г1оу2А'1- Это кодиро- вание обозначается функцией о: А —> {О, I}”, которая сопоставляет элементам из А различные битовые «-вектора. Пусть с,(а) обозначает z-й бит этого вектора. Функция f. А —>А, отображающая элементы А на элементы А, представлена вектором из п бу-
Глава 12 Прочие граф-модели 931 левых функций f, где каждая функция {О, 1}"—> {О, 1} определяется как /(о(а)) = = Во многих реальных приложениях области обладают "естественным" порядком (на- пример, бинарное кодирование целых чисел); для других областей порядок строится искусственно Например, символьный симулятор COSMOS использует OBDD для символьного рас- чета поведения транзисторной схемы. Такой симулятор может быть использован для автоматической генерации тестов для поиска ошибок в схеме и для формальной про- верки того, отвечает ли поведение схемы некоторым заданным критериям. В модели схемы напряжение в узлах представлено трехзначным сигнальным набором, в кото- ром значения 0 и 1 обозначают низкое и высокое напряжение, а третье значение, X, обозначает неизвестное или потенциально нецифровое напряжение. Во время сим- вольного моделирования состояния вершин должны быть вычислены как трехзнач- ные функции над множеством булевых переменных, введенных пользователем для представления первичных входных данных или начального состояния. COSMOS представляет состояние вершины парой OBDD-диаграмм. А именно, он кодирует каждый из N= 3 элементов сигнального набора вектором из и = 2 бинарных значений в соответствии с кодирующей функцией: о(0) = [0, 1], о(1) = [1, 0], с(Х) = [1, 1]. Функции следующего состояния, вычисляемые симулятором, полностью определя- ются в соответствии с этим булевым кодированием, что дает возможность точно опи- сать булевыми функциями поведение схемы. В табл 12 4 приведен пример трехзнач- ного расширения операций AND, OR и NOT. Заметим, что операции дают значение X в каждом случае, когда неизвестный аргумент может вызвать неопределенность в значении функции. Пусть [яь а0] обозначает кодировку трехзначного сигнала а, тогда трехзначная операция может быть полностью выражена в терминах булевых опера- ций: [а,, ао] fe0] = [Qi • bx, «0+£>0], [а,, а0] +,[*ь ^о] = [«i+^i, ao bo], [а,,а0]' = = [«0, 01]- Таблица 12.4. Трехзначное расширение операций AND, OR и NOT. Третье значение X обозначает неизвестное или потенциально нецифровое напряжение -Г 0 1 X 0 0 0 0 1 0 1 X X 0 X X , +t 0 1 X 0 0 I X 1 1 I 1 X X I X а а' 0 1 1 0 X X Во время функционирования симулятор действует подобно обычному логическому симулятору, управляемому событиями. Вначале каждый внутренний узел инициали- зируется значением [I, 1], означающим, что значение узла неизвестно независимо от обстоятельств. В процессе моделирования состояния узлов модифицируются с по-
932 Часть II. Применение графов и граф-моделей мощью вычисления булевого представления функции следующего состояния с при- менением операции APPLY. Каждый раз, когда состояние узла перевычисляется, ста- рое состояние сравнивается с новым, и в случае, когда они неэквивалентны, создается событие для каждого разветвления этого узла. Процесс продолжается до тех пор, по- ка список событий не становится пустым, указывая на то, что сеть находится в ста- бильном состоянии. Этот метод обработки событий требует наличия эффективного способа проверки эквивалентности. Множества Пусть задано базисное множество А. Мы можем представлять и обрабатывать его подмножества, используя "характеристические функции". Множество Sc А обозна- чается функцией {0, 1}"—> {О, I}, Xs(*) = XПХ/ где ® представляет «еХ1<;<л собой дополнение операции EXCLUSIVE-OR. Теперь операции над множествами (подмножествами) могут быть реализованы с помощью булевых операций на их ха- рактеристических функциях, например: Хи := 0, x.su7:= Хх + Xr> Ххп.7-:= X.x X/, Хх-7':=- Хх ’ X/- • Множество .S’ является подмножеством Т в том и только том случае, если x.v • Ху- = 0- Многие приложения, использующие OBDD, строят и обрабатывают множества даже без явной нумерации их элементов. Вместо этого можно представить (непустое) множество как множество возможных выходных значений вектора функ- ций, т. е. можно полагать, что функция f обозначает множество {« | с(«) =f(b) для некоторого Ь е {0, 1}"}. Это представление может оказаться удобным для приложе- ний, в которых анализируемая система представлена вектором функций. Модифици- руя эти функции, мы можем также представлять подмножества состояний системы. Отношения Мы можем определить А-арное отношение как множество упорядоченных кортежей размерности к. Следовательно, отношения также могут быть представлены и обрабо- таны с помощью характеристических функций. Рассмотрим в качестве примера би- нарное отношение RcA * А, обозначаемое булевой функцией х«, которая определя- ется следующим образом: х«(х,у)= X X Пл ® п'(а) Ш ® п' аеА ЬеА |_1</<л J Ll</<n aRh С помощью этого представления мы можем производить такие действия, как пересе- чение, объединение и разность отношений, применяя булевы операции к их характе- ристическим функциям. Комбинируя функциональную композицию и квантификацию переменных, мы можем также получать составные отношения: -= 3 х [Х/< (x,z ) - хх (?,У )], где R ° .S’ обо- значает композицию отношений R и S. Квантификация над вектором переменных включает квантификацию каждого элемента вектора в любом порядке. Далее, мы
Глава 12. Прочие граф-модели 933 можем вычислить транзитивное замыкание отношения, используя метод неподвиж- ной точки. Функция X/?» вычисляется как предел последовательности функций каждая из которых определяется с помощью соотношений Ro = I и Л,+1 = I о R ° R, для всех / > 0, где / обозначает тождественное отношение. Процесс вычисления схо- дится, когда он достигает такой итерации i, что Хл = Хт+ ь для чег0 вновь потребует- ся эффективная проверка эквивалентности. Если мы предположим, что R представля- ет граф, с вершиной для каждого элемента А и дугой для каждого элемента R, тогда отношение R, обозначает пары вершин, достижимые по путям длиной не более чем i дуг. Следовательно, вычисление должно сходиться максимум за N- 1 итераций, где А=|Л|. Техника, известная как "метод итеративных квадратур", сокращает макси- мальное количество итераций до и = Tlog2 7V~l Каждая итерация вычисляет отношение 7?0, указывающее на пары вершин, достижимых по путям, не длиннее 2": 7?<о) = 1 R, 7?(,+1) = ° 7?(0. Многие приложения OBDD содержат обработку отношений над очень большими множествами, и поэтому сокращение числа итераций с W (например, 109) до и (например, 30) может быть очень существенным. 12.1.4. Другие применения OBDD широко используются в разработке, верификации и тестировании цифровых систем связи. Рассмотрим методы их применения в некоторых областях. Верификация OBDD могут быть использованы непосредственно для установления эквивалентности двух комбинаторно-логических схем. Эта проблема возникает в случаях, когда необ- ходимо сравнить схему и сеть, полученную из спецификаций системы, либо когда требуется проверить, не изменил ли логический оптимизатор функциональность схе- мы. Вначале с помощью операции APPLY вычисляются функциональные представ- ления обеих сетей и затем проверяется их эквивалентность. Этот метод позволяет также сравнивать две последовательные системы, если они используют одно и то же кодирование состояний, а именно — если они имеют идентичные выходные данные и функции перехода (к следующему состоянию). Коррекция ошибок схемы Не довольствуясь простым обнаружением ошибок в логической схеме, можно созда- вать методы автоматической коррекции дефектных схем. Существующие методы коррекции включают рассмотрение относительно небольшого класса потенциальных ошибок, таких как одиночный некорректный логический элемент, и определение то- го, может ли какой-либо вариант данной цепи достичь требуемой функциональности. Этот анализ демонстрирует мощь операций квантификации при вычислении проек- ций, в данном случае производя проекцию первичных входных значений посредством универсальной квантификации. Такой анализ может быть проведен символически, с помощью кодирования возмож- ных функций элементов булевыми переменными. Как показано на примере (рис. 12.10), произвольный А-входовый канал может быть моделирован 2*-входовым
934 Часть II. Применение графов и граф-моделей мультиплексором, где операция элемента определена входными данными мультип- лексора a. Рассмотрим контур А с одним входом, в котором один из логических эле- ментов заменен таким блоком, это дает в итоге функциональность сети А (Я, а), где х представляет множество первичных входных значений. Предположим, что желаемая функциональность есть S(x). Наша задача— определить, могут ли (и если могут, то каким образом) две функции быть сделаны идентичными для всех значений первичных данных посредством подходящего "программирования" элемента. Это включает вы- числение функции С(а), определенной следующим образом: С(5) = Х/х [N(x,a) Ф Ф Д(х’)] Серьезные ошибки схемы не могут быть исправлены таким образом, он позволяет избежать утомительной коррекции часто встречающихся ошибок, таких как неправильное расположение инверторов или использование некорректного типа логического элемента. Эта задача также оказывается полезной в логическом синтезе, когда требуется изменить схему таким образом, чтобы она соответствовала изменен- ной спецификации. Рис. 12.10. Блок функции всеобщности. Присваивая различные значения переменным о, можно реализовать произвольную 2-входовую операцию Анализ чувствительности Другой класс приложений включает составление характеристик того влияния, кото- рое оказывают изменения значений сигналов различных проводов комбинаторной схемы. А именно, для каждого значения сигнала s мы хотим вычислить булеву разни- цу для каждого первичного выходного значения относительно ,s\ Этот анализ может быть проведен символически, с помощью введения в сеть "преобразователей сиг- нального провода", как показано на рис. I2.l I. Для каждого провода, в обычной си- туации передающего сигнал s, мы избирательно изменяем значение сигнала, которое теперь равно s', при помощи булевого значения Дд: s' = s Ф Д,. Мы можем определить условия, при которых некоторое выходное значение схемы оказывается чувствительным к значению сигнального провода, сравнивая выходные значения исходной и замененной схем, как показано на рис. 12.12. Как видно из этого
Глава 12. Прочие граф-модели 935 рисунка, мы можем даже вычислить влияние каждого однопроводного преобразова- ния в схеме за одно символическое вычисление. А именно, пронумеруем каждый сиг- нальный провод числами от 1 до т — 1 и введем множество flog т\ "перестановочных переменных" г . Каждый перестановочный сигнал Р„ затем определяется как функ- ция, принимающая значение 1 в случае, когда перестановочные переменные являются бинарным представлением номера, присвоенного сигналу 5. В терминах построения логических схем это эквивалентно генерации перестановочных сигналов декодером с г на входе. Полученная функция Т{ х, г ) принимает значение 1, если исходная схема и схема, полученная с помощью перестановки г, выдают одни и те же выходные зна- чения на входных значениях х . Рис. 12.11. Преобразователь сигнального провода. Ненулевое значение Ps изменяет значение, передаваемое по этому проводу Рис. 12.12. Вычисление чувствительных к однопроводным преобразованиям участков. Каждое присваивание переменной г вызывает изменение значения ровно одного провода Одной областью приложения такого анализа чувствительности является автоматиче- ская генерация тестов. Функция чувствительности описывает множество всех тестов для каждой одиночной ошибки. Предположим, что сигнальный провод, помеченный бинарным номером Ь, в обычной ситуации имеет в схеме функцию s(x). Тогда вход- ной шаблон а будет обнаруживать ошибку типа "отсутствие сигнала на проводе 1"
936 Часть II. Применение графов и граф-моделей в том и только том случае, если T(a,b) s(a) =0. Подобным же образом шаблон a будет обнаруживать ошибку типа "отсутствие сигнала на проводе 0" в том и только том случае, если Т(а,Ь) s(a) = 1. Этот метод также может быть распространен на последовательные схемы и на схемы, представленные на уровне переключа- телей. Второй областью приложения является комбинационно-логическая оптимизация. Для сигнального провода, имеющего бинарный номер Ь, функция Т(х,у) представляет набор "безразличностей" для каждого провода схемы, т. е. таких случаев, когда вы- ходные значения схемы не зависят от сигнального значения этого провода. Руко- водствуясь этой информацией, оптимизатор схемы может применять такие преоб- разования, как удаление сигнального провода или перемещение провода на другой выходной элемент. Недостаток этого подхода состоит в том, что функция чувстви- тельности должна вычисляться заново каждый раз, как оптимизатор изменяет схему. Альтернативный подход дает более ограниченный, но и более компактный набор функций "безразличностей", в котором наборы "безразличностей" остаются действи- тельными даже в случаях, когда меняется структура схемы. Вероятностный анализ Существует метод для статистического анализа влияния меняющейся задержки сиг- нала в цифровой схеме. Это приложение OBDD выглядит особенно интригующим, поскольку здравый смысл заставляет считать, что такой анализ требует вычисления реальных вариаций параметров и в силу этого не может быть закодирован булевыми переменными. Рассмотрим сеть логических элементов, в которой каждый элемент имеет задержку, задаваемую некоторым вероятностным распределением. Эта схема демонстрирует диапазон вариантов поведения, некоторые из которых классифицируются как неже- лательные. "Выход" определяется как вероятность того, что нежелательное поведение не встретится. На рис. 12.13 приведен пример простой схемы, где два из логических элементов имеют переменное распределение задержек; мы хотим оценить вероят- ность появления сбоя в вершине Out, в то время как входной сигнал А совершает пе- реход из 0 в 1. Нужно провести анализ ситуации, когда сигнал А изменяет свое значе- ние на 1 в момент времени 0. Сигналы С и D совершают переход, для которого из- вестно вероятностное распределение времени перехода. Необходимо провести однократный простой анализ для расчета вероятной формы волны для всех сигналов, как если бы они распределялись независимо. Затем мы сможем легко вычислить по- ведение каждого выходного значения схемы в соответствии с функцией элемента и формой входной волны. Например, если мы рассматриваем сигналы С и D как неза- висимые, мы можем вычислить вероятность приближающегося перехода в вершине Out в момент времени t как произведение вероятности того, что С совершает переход в момент Z, и вероятности того, что D не совершает перехода во время меньше t. Это приводит к такому вероятностному распределению, что конечная вероятность реали- зации перехода (т. е. сбоя) оказывается равной 30%. В действительности, разумеется,
Гпава 12. Прочие граф-модели 937 время прохождения сигналов С и D в значительной степени коррелирует друг с дру- гом — оба подвержены влиянию задержки начального буферного элемента. В силу этого более тщательный анализ даст такое вероятностное распределение времени перехода, помеченное "Out", что в результате конечная вероятность реализации пере- хода оказывается равной 12,5%. Таким образом, упрощенный анализ недооценивает выход схемы. В других случаях упрощенный анализ может переоценивать выход схемы. Рис. 12.13. Схема с неопределенными задержками. Логические элементы помечены своими минимальными и максимальными задержками. Инверторы имеют распределение задержек Чтобы решить эту проблему с помощью символьного булева анализа, мы должны принять два ограничения. Во-первых, все задержки схемы должны иметь целочис- ленные значения (с помощью подходящего выбора единицы времени), в силу чего переходы будут совершаться в дискретных временных точках. Во-вторых, вероят- ность задержки должна быть кратной значению l/А, где к— некоторая степень двой- ки. Например, оба переменных элемента на рис. 12.13 имеют задержки от 1 до 4. Один имеет равномерное распределение задержек [1/4, 1/4, 1/4, 1/4], тогда как у дру- гого распределение задержек приближается к нормальному [1/8, 3/8, 3/8, 1/8]. Затем значение задержки для элемента может быть закодировано множеством из log к буле- вых переменных, как показано на рис. 12.14. А именно, мы моделируем компонент схемы /r-входовым мультиплексором, в котором значение задержки, имеющее веро- ятность с/к, подается на с входов. Затем схема рассчитывается с использованием сим- вольного расширения обычного алгоритма симуляции логических схем. Значение сигнала в вершине N в каждый момент времени t является булевой функцией A(z) от переменных задержки. Предположим, что в примере на рис. 12.15 переменные [еь е0] кодируют задержку между А и В, тогда как переменные [d2, dt, d0] кодируют задержку между В и С, как показано в табл. 12.5. Для времени /<0 функции вершин будут следующими: А(1) = B(t) = D(t) = Out(/) = О, С(7) = 0. Для времени t > 0 вершина А имеет функцию A(l) = 1, остальные функции вычисляются следующим образом:
938 Часть II. Применение графов и граф-моделей B(i) = е} -е0 A(t- 1)+е, -ео^(/-2)+егео A(t - 3) + еге0 А(1 - 4), C(t)=d2 d\ -d0 B(t-i) + d2 (dt+ </>)• B(t -2)+d2( dt +d0 ) B(t -3) + d2-dvd0- B(t-4), D(t) = B(t - 3), Out(f) = C(/) • D(f). Значение выходного сигнала мы можем получить из этих уравнений как Out(t) = 0 для /<3 и t> 8. Для других значений времени значение сигнала будет вычисляться сле- дующим образом: Out(4) = d2 • d[ d0 e} • e0 , Out(5) = d2 • dt • d0 • e, • e0, Out(6) = d2 • d\ d0 • • e0, Out(7) = d2 d\ d0 • e0. Рис. 12.14. Схема моделирования неопределенных задержек. Булевы переменные управляют выбором задержки Сигналы повторяются в соответствии с распределением задержек Мы можем вычислить булеву функцию, показывающую условия задержки, при кото- рых встречается некоторое нежелательное поведение. Например, мы можем вычис- лить вероятность того, что сбой происходит в вершине Out, как G = EOut(t). В этом случае мы можем вычислить G = d2 dt d0, т. е. вероятность того, что сбой происхо- дит в том и только том случае, когда задержка между В и С равна 4. Пусть дана булева функция, представляющая условия, при которых происходит неко- торое событие. Мы можем вычислить вероятность события путем вычисления плот- ности функции, т. е. доли присваиваний переменным, на которых функция принимает значение 1. С помощью Шенноновского раскрытия мы можем задать плотность р(/) функции f рекурсивным образом: р(1) = 1, р(0) = 0, р(/) = 1/2[р(/| х<_0) + p(/’|Jt<_i)]. Та- ким образом, при наличии OBDD-представления/мы можем вычислить плотность за линейное время путем обхода графа в глубину, помечая каждую вершину плотностью функции, обозначающей ее подграф. На рис. 12.15 изображено такое вычисление для OBDD, представляющего условия, при которых вершина С на рис. 12.13 содержит переход в момент времени 6, помечая ее вероятностью этого события, равной 7/32.
Гпава 12. Прочие граф-модели 939 Рис. 12.15. Вычисление плотности функции. Каждая вершина помечена долей присваиваний переменным, дающих в результате 1 Как демонстрирует этот пример, основанный на OBDD символьный анализ может быть применен к системам со сложными вариациями параметров. Хотя при этом тре- буется упростить проблему таким образом, чтобы было возможно рассматривать только дискретные вариации, все-таки могут быть получены хорошие результаты. Основным достоинством этого подхода по сравнению с другими упрощенными мето- дами вероятностного анализа (например, измерение управляемости и наблюдаемости) является то, что он точно вычисляет влияние корреляций между стохастическими значениями. А->В Задержка Условия 1 2 3 4 е, е0 е| ' е0 ei е0 е1 е0 Таблица 12.5. Условия задержки для схемы моделирования неопределенных задержек В-»С Задержка Условие 1 -М 0^1 2 + с/’о) 3 6?2 ' ( ^1 + ^0 ) 4 6^2 * ^4 " ^4)
940 Часть II. Применение графов и граф-моделей Анализ конечных автоматов Многие задачи в таких областях, как верификация цифровых систем, проверка прото- колов и оптимизация последовательных систем, требуют детальной характеризации конечного автомата над последовательностью переходов. Классические алгоритмы для задачи характеризации осуществляют явное представление автомата в виде диа- граммы переходов и затем анализируют структуру путей и циклов в этой диаграмме. Однако эти методы непрактичны, если количество состояний становится большим. К сожалению, даже относительно маленькие цифровые системы могут иметь очень большие пространства состояний. К примеру, один 32-битный регистр может иметь около 4 х 109 состояний. Существуют "символьные" методы описания автоматов, в которых структура перехо- дов представлена в виде булевой функции. Вначале выбираются бинарное кодирова- ние состояний системы и входной алфавит. Поведение, связанное со следующим со- стоянием, описывается как отношение, задаваемое характеристической функцией 5(х,о,л), которая принимает значение 1 в случае, когда входное значение х может вызвать переход из состояния о в состояние п . На рис. 12.17 приведен пример OBDD-представления недетерминированного автома- та, диаграмма переходов которого изображена на рис. 12.16. В этом примере три возможных состояния представлены с помощью двух бинарных значений посредст- вом кодирования: а(Л) = [0, 0], о(В) = [1,0], о(С) = [0, 1]. Заметим, что неиспользо- ванное значение [1, 1] может рассматриваться как "безразличное" для аргументов о и и функции 5. В представлении OBDD на рис. 12.17 эта комбинация используется как альтернативный код состояния С для упрощения OBDD-представления. Для такого маленького автомата OBDD-представление не является улучшением по сравнению с явным представлением. Но для более сложных систем OBDD-пред- ставление может быть значительно меньшим. Основываясь на оценках сложности сетей с ограниченной шириной, можно охарактеризовать некоторые условия, при которых OBDD-диаграмма, кодирующая отношение переходов системы, растет ли- нейно относительно количества компонентов системы, тогда как количество состоя- ний растет экспоненциально. В частности, это свойство имеет место в тех случаях, когда справедливы следующие два условия: □ компоненты системы связаны в линейную или древесную структуру; □ каждый компонент поддерживает только ограниченное количество информации о состоянии других компонентов. Как показывает пример на рис. 12.5, это ограничение выполняется также для кольце- вых структур, т. к. кольцо может быть "сплющено" в линейную цепь двунаправлен- ных ссылок. Если имеется OBDD-представление, то свойства системы с конечным числом состоя- ний могут быть выражены в терминах уравнений с неподвижной точкой над функци- ей перехода, и эти уравнения могут быть решены с использованием итеративных ме- тодов, подобных тем, которые использовались для нахождения транзитивного замы-
Гпава 12. Прочие граф-модели 941 кания отношения. Рассмотрим, например, задачу определения множества состояний, достижимых из начального состояния с бинарной кодировкой q после некоторой последовательности переходов. Пусть отношение S обозначает условия, при которых для некоторого начального значения х может существовать переход из состояния о в состояние л. Это отношение имеет характеристическую функцию Xs(o,n) = = 3 х [5(х,о,л)1- Множество состояний, достижимых из состояния q, имеет харак- теристическую функцию »(.? ) = x.s( q,s ). С помощью этого метода были проанализированы системы с числом состояний более 1О20, это намного больше, чем было возможно анализировать с помощью методов, основанных на явных представлениях диаграмм переходов. Известны также усовер- шенствования, способствовавшие ускорению сходимости и уменьшению размера промежуточных OBDD. Рис. 12.16. Явное представление недетерминированного конечного автомата. Размер представления растет линейно относительно количества состояний Рис. 12.17. Символьное представление недетерминированного конечного автомата. Количество переменных растет логарифмически относительно количества состояний
942 Часть II. Применение графов и граф-моделей К сожалению, те характеристики системы, которые гарантируют эффективность OBDD-представления отношения перехода, не дают возможности найти подходящие верхние границы для результатов, генерируемых символьным анализатором конеч- ных автоматов. Например, существуют примеры систем, имеющие линейную струк- туру внутренних соединений, для которых характеристическая функция множества достижимых состояний требует OBDD-представления экспоненциального размера. С другой стороны, на практике было обнаружено, что большое количество реальных систем могут анализироваться рассмотренными методами. Одним из приложений анализа конечных автоматов является проверка корректности последовательной цифровой схемы. Например, можно доказывать, что конечный ав- томат, выведенный из спецификаций системы, эквивалентен другому автомату, выве- денному из схемы, даже если его кодирование состояний отличается от первого. Для этого применения также были разработаны более специальные методы, использую- щие характеристики верифицируемой системы, например, того, что схема является синхронной и детерминированной, и что спецификация требует анализировать только ограниченное количество тактов. С их помощью, например, были верифицированы конвейерные маршруты данных, содержащие более 1000 бит состояния регистра. Та- кая система, имеющая более чем 1О300 состояний, превосходит возможности совре- менных символьных методов, основанных на диаграммах переходов. Другие области применения Исторически сложилось так, что вначале OBDD применялись в основном в задачах разработки цифровых систем, верификации и тестирования. Однако в последнее вре- мя они получили применение в других областях. Например, техники с использовани- ем неподвижной точки, применяемые при символьном анализе конечных автоматов, могут быть полезными при решении множества проблем математической логики и формальных языков, если предметные области в них являются конечными. Также было обнаружено, что проблемы многих приложений могут быть сформулированы в виде набора уравнений над булевыми алгебрами, которые поддаются решению не- которым унифицированным образом. В области искусственного интеллекта была разработана система поддержки истинно- сти, основанная на OBDD. Она использует OBDD для представления "базы данных", т. е. известных отношений между элементами. Было обнаружено, что с помощью ко- дирования базы данных в этой форме система может делать заключения быстрее, чем при традиционном подходе, когда она просто ведет список "известных фактов". На- пример, распознавание того, согласуется ли новый факт с множеством существую- щих фактов или следует ли он из них, представляет собой простую проверку импли- кации. Возможности улучшения Существует большое множество различных проблем, которые были успешно решены с помощью основанной на OBDD символьной обработки. Вместе с тем имеется нема- ло задач, для решения которых требуются более адекватные методы. Конечно, боль- шинство этих задач являются WP-трудными и иногда даже Р£Р/1С£-трудными. Сле- довательно, мало вероятно, что для их решения может быть найден метод с полино-
Гпава 12. Прочие граф-модели 943 миальной сложностью. Лучшее, что можно сделать, — это разработать методы, по- зволяющие за приемлемое время решать большинство интересующих нас задач. Одна из возможностей на пути к этому состоит в улучшении самого представления. При работе с цифровыми системами, содержащими умножители и другие функции, включающие сложные отношения между управляющими сигналами и сигналами дан- ных, OBDD-представления быстро становятся нереально большого размера. Было предложено несколько методов, основанных на тех же общих принципах, что и OBDD, но с менее строгими ограничениями на структуры данных. Среди них 1FED- представления (или "If-Then-Else-DAGs"), где условие проверки в каждой вершине может быть более сложной функцией, чем обычная проверка переменной, "свобод- ные бинарные диаграммы решений", в которых ограничение на порядок переменных заменяется на условие, что ни один путь из корневой вершины в терминальную не проверяет одну и ту же переменную более одного раза, "однократно ветвящиеся про- граммы", которые обладают многими полезными свойствами OBDD, включая эффек- тивный (хотя и вероятностный) метод проверки эквивалентности. В каждом из этих расширений метода, основанного на OBDD, делается попытка найти компромисс ме- жду компактностью представления и трудностью его построения или проверки его свойств. Во многих задачах комбинаторной оптимизации символьные методы, использующие OBDD, не показали столь же высокую производительность, как более традиционные методы. Это связано с тем, что в этих задачах обычно требуется найти только одно решение, удовлетворяющее некоторому критерию оптимальности. Напротив, боль- шинство основанных на OBDD подходов вычисляют все возможные решения и затем выбирают лучшее из них. К сожалению, многие задачи имеют слишком много реше- ний, чтобы можно было их символически закодировать. Более традиционные методы поиска, такие как метод ветвей и границ, часто оказываются более эффективными и способными решать большие задачи. Одна из возможностей улучшения состоит в использовании идеи "ленивого" или "отложенного" исполнения при обработке с ис- пользованием OBDD. Вместо того, чтобы немедленно создавать полное представле- ние каждой функции в процессе выполнения последовательности операций, следует пытаться строить только те OBDD, которые нужны для вывода окончательной ин- формации. 12.2. Частично упорядоченные множества 12.2.1. Основные определения Частично упорядоченным множеством называется любая пара [5, < ], где < — час- тичный порядок на 5. Если < — линейный порядок, то частично упорядоченное мно- жество (сокращенно чу-множество) называется линейно упорядоченным, или цепью. А. Всякое подмножество S чу-множества Р само является чу-множеством отно- сительно того же самого порядка, ограниченного на S. В частности, любое под- множество цепи является цепью.
944 Часть II. Применение графов и граф-моделей Чу-множество Р может содержать самое большее один элемент О, который удовле- творял бы неравенству О<х для всех х е Р (наименьший элемент). Двойственный ему наибольший элемент множества Р, если он существует, обозначается символом /. Элементы Он/, когда они существуют, называются универсальными гранями чу- множества Р. Подмножество Хс Р называется ограниченным, если существуют а, Ь е Р такие, что а < х < Ь для всех х е X. Существуют чу-множества без универсальных граней. Таково множество веществен- ных чисел [А, < ] с обычным отношением порядка (если оно не расширено формаль- ным присоединением -оо и оо). Б. В любом чу-множестве [5, < ] может существовать не более одного наименьше- го и не более одного наибольшего элемента. Пусть Р = [5, <] — чу-множество, а и Ь — его элементы. Говорят, что а доминирует над Ь, если а > Ь, но ни для какого х е S неверно, что а > х > Ь. Отношение < одно- значно восстанавливается по данному отношению доминирования в любом конечном чу-множестве; а именно, имеет место следующее свойство. В. Пусть а < Ь в конечном чу-множестве Р. Тогда Р содержит по крайней мере одну цепь х0 = а < Х[ < ... < х, — Ь, в которой каждый из элементов х, (I = 1, ], t) доминиру- ет над х,_|. Элемент т чу-множества [S, < ] называется минимальным, если не существует такого элемента х е S, что х < т. Элемент т называется максимальным, если не существует такого элемента х е S, что х > т. Очевидно, что если частично упорядоченное множе- ство обладает универсальной нижней гранью, или наименьшим элементом О, то О является единственным минимальным элементом. Г. В любом конечном чу-множестве есть хотя бы один минимальный элемент. Чу-множество [S, < ], обладающее свойством, что каждое непустое подмножество содержит максимальный элемент, называется множеством, удовлетворяющим усло- вию возрастающих цепей. Если каждое непустое подмножество содержит минималь- ный элемент, тогда говорят, что 5 удовлетворяет условию убывающих цепей. Множе- ство S удовлетворяет условию возрастающих цепей тогда и только тогда, когда оно не содержит бесконечной последовательности элементов xt, х2 < такой что X] < х2 < ...; аналогично оно удовлетворяет условию убывающих цепей, если оно не содержит бесконечной последовательности элементов xt, х2, х3,... такой, что х}> х2> х3 >.... Элементы х и у чу-множества [S, < ] называются сравнимыми, если х < у или у < х, и несравнимыми — в противном случае. Очевидно, что чу-множество является цепью, если любые два элемента его сравнимы. Если цепь удовлетворяет условию убываю- щих цепей, то она называется возрастающей хорошо упорядоченной цепью. Анало- гично, чу-множество называется убывающей хорошо упорядоченной цепью, если она удовлетворяет условию возрастающих цепей. Все цепи в чу-множестве конечны, если оно удовлетворяет как условию возрастающих цепей, так и условию убывающих цепей. Пусть S— некоторое подмножество чу-множества Р. Элемент а е Р называется нижней границей, или минорантой, множества S, если а < х для всех х е S. Элемент
Гпава 12. Прочие граф-модели 945 о'называется верхней границей, или мажорантой, множества S, если а'> х для всех х е 5. Элемент b е Р называется нижней гранью S, если он является нижней границей для S и Ь> Ь' для любой другой нижней границы Ь' множества S. В этом случае пи- шут b = infS. Аналогично, элемент с е Р называется верхней гранью множества S, если с является верхней границей для S и с < с'для любой другой верхней границы с'. В этом случае пишут с = sup S'. Д. Любое подмножество чу-множества имеет не более одной верхней и не более одной нижней грани. Лемма Цорна. Если [S, < ] — чу-множество такое, что каждая цепь элементов в S имеет верхнюю грань в S, то S имеет по крайней мере один максимальный элемент. Наиболее удобным представлением чу-множества [S, < ] является представление с помощью орграфа, вершины которого суть элементы множества S. Вместо произ- вольного изображения такого графа на плоскости используют специальное, когда для любых элементов х, у е S’ вершина х располагается выше вершины у всякий раз, когда у < х. Вершина х на более высоком уровне непосредственно смежна с вершиной у, если х доминирует у, т. е. не существует такого z е S, что у < z < х. При таком распо- ложении вершин отпадает необходимость указывать ориентацию дуг и можно счи- тать граф неориентированным. Этот неориентированный граф называется диаграм- мой Хассе чу-множества. Рис. 12.18 представляет диаграмму Хассе множества всех подмножеств множества {1,2,3}, упорядоченного относительно включения мно- жеств. Рис. 12.18. Диаграмма Хассе для множества всех подмножеств множества {1, 2, 3} Функция 6 : Р Q, заданная на чу-множестве Р и принимающая значения из чу- множества Q, называется сохраняющей порядок (монотонной или изотопной), если из х < у следует, что 0(х) < 0(у). Изотонная функция, допускающая изотонную обрат- ную функцию, называется изоморфизмом. Другими словами, изоморфизм между двумя чу-множествами есть взаимно-однозначное соответствие 6 между ними, кото- рое удовлетворяет условию изотонности и условию того, что из 0(х) < 0(у) следует х < у (обратная изотонность функции 6).
946 Часть II Применение графов и граф-моделей Два чу-множества Р и Q называются изоморфными (обозначение: Р = Q), если суще- ствует изоморфизм между ними. Изоморфизм чу-множества Р с самим собой называ- ется его автоморфизмом. Функция 0: Р —> Q называется антиизотонной (антитонной), если из х < у следует, что 6(х) > 60’). Взаимно-однозначное соответствие 6, удовлетворяющее условию антиизотонности и условию того, что из 6(х) < 00) следует х > у, называется дуальным изоморфизмом или антиизоморфизмом. Чу-множество, антиизоморфное себе, называется самодвойственным. Например, са- модвойственным является множество всех линейных подпространств «-мерного евк- лидова пространства, содержащих начало, т. к. соответствие, соотносящее каждому подпространству его ортогональное дополнение, взаимно однозначно и обращает включение. 12.2.2. Параметры чу-множеств Пусть Р— цепь, содержащая п элементов. Будем говорить, что длина ее равна п - 1. В общем случае длиной /[Р] чу-множества Р называется точная верхняя грань длин цепей в Р. Если 7[Р] конечна, то Р называется множеством конечной длины. Любое такое множество с точностью до изоморфизма определяется своим отношением покрытия (дом инирован ия). Пусть Р— чу-множества конечной длины с наименьшим элементом О. Высотой или размерностью И(х) элемента х называется точная верхняя грань длин цепей О = х0< <Х\ < ... < xt = х между О и х. Если Р имеет наибольший элемент /, то, очевидно, h[I\ = Д/Ч- Понятно также, что й[х] = 1 тогда и только тогда, когда х покрывает О, такие элементы называются атомами или точками чу-множества. Подмножество А чу-множества Р называется антицепью в Р, если оно содержит по- парно несравнимые элементы. Шириной w[P] чу-множества Р называется число эле- ментов в наибольшей антицепи в Р. Множество J(P) всех антицепей чу-множества Р может быть упорядочено следующим образом: А </</-) В тогда и только тогда, когда для всех х е А найдется такой элемент у е В, что х <Ру. Пусть Р— чу-множество. Расширением L чу-множества Р называется такое чу- множество, что х >у в Р влечетх > у в L. Размерностью dim(P) частичного порядка Р называется наименьшее целое t, для которого Р может быть представлено как пересе- чение t его линейных расширений (вложено в произведение t цепей). Множество ли- нейных расширений, чье пересечение порождает Р, называется реализацией Р. Есте- ственным обобщением размерности является требование, чтобы цепи, используемые в произведении, имели длину не больше к. Этот инвариант называется ограниченной размерностью и обозначается dim*(/’). Весьма интересен случай dim2, т к. dim2(/>) есть наименьшее целое t такое, что Р может быть представлено семейством подмно- жеств некоторого множества Q, упорядоченным относительно включения.
Глава 12. Прочие граф-модели 947 Квазипорядок Существует класс отношений, более общих, чем отношения порядка. Типичным при- мером может служить отношение делимости в любом коммутативном моноиде. Из- вестно, что оно рефлексивно и транзитивно. Квазипорядком на множестве 5 называется любое рефлексивное и транзитивное би- нарное отношение Q. Квазиупорядоченным множеством [Р, Q] называется пара, со- стоящая из множества и квазипорядка на нем. Очевидно, что всякое чу-множество является квазиупорядоченным множеством. Об- ратное неверно, т. к. квазипорядок может не быть антисимметричным. Пусть в квазиупорядоченном множестве Р = [5, Q] введено отношение х~у; оно означает, что xQy и yQx. Тогда справедливы следующие свойства. А. Отношение ~является отношением эквивалентности на S. Б. Если Е и F— два класса эквивалентности относительно ~, то либо ни для каких х е Е,у е F неверно, что xQy, либо для всех х е Е,у е F верно, что xQy. В. Пусть Е < F означает, что xQy для некоторых (и потому для всех) х е Е,у е F. Фактор-множество S/ ~ частично упорядочено относительно этого отношения. 12.2.3. Частично упорядоченные множества и графы Орграф G называется транзитивным, если для любых двух его дуг (а, Ь) и (Ь, с) су- ществует замыкающая их дуга (а, с). Каждый орграф имеет транзитивное замыка- ние, которое представляет собой наименьший содержащий его транзитивный орграф G и транзитивную редукцию, которая представляет собой орграф с наименьшим числом дуг, транзитивное замыкание которого есть также G. Если граф G — бескон- турный, добавление замыкающих дуг не может привести к появлению в нем контура. Из определения частичного порядка вытекает следующее свойство: А. Любой орграф без кратных дуг является графом частичного упорядочения. Орграф является графом полного упорядочения, если для любых вершин а, Ь выпол- няется одно из соотношений а < b или b < а, и графом слабого упорядочения, если выполняется хотя бы одно из указанных соотношений. В отличие от графа полного упорядочения граф слабого упорядочения может иметь контуры. Две вершины в G называются сравнимыми, если для них выполняется одно из соот- ношений а < Ь или b < а, и несравнимыми — в противном случае. Граф G является графом полного упорядочения, если все его вершины сравнимы. Определим блок в орграфе как блок в неориентированном графе, получаемым из дан- ного орграфа заменой каждой дуги ребром. Справедливы следующие свойства: Б. Любой орграф G является частичным графом некоторого графа полного упоря- дочения с теми же блоками, что и G.
948 Часть II. Применение графов и граф-моделей В. Любой орграф G может быть представлен как пересечение графов слабых упо- рядочений, содержащих G и имеющих то же множество контуров, что и G. Г. Любой бесконтурный орграф есть пересечение графов полных упорядочений, в которых он содержится. Часть Н орграфа G называется порождающей частью, если достижимые множества для всех вершин одни и те же для Н и для G. Для того чтобы граф Н обладал этим свойством, необходимо и достаточно, чтобы для каждой дуги {а, Ь) в G существовал путь Рн (а, Ь) в Н. Минимальный порождающий граф для G называется транзитив- ной редукцией. Таким образом, порождающий граф Н будет транзитивной редукцией тогда и только тогда, когда удаление любой дуги из Н изменяет достижимость в Н. Что касается единственности транзитивной редукции, то назовем дугу е графа G су- щественной, если она принадлежит каждому порождающему графу для G. Очевидно, это равносильно тому, что е не является излишним в G. Таким образом, существен- ные дуги принадлежат каждой транзитивной редукции, если таковые существуют. Д. Для того чтобы G имел единственную транзитивную редукцию, необходимо и достаточно, чтобы для каждой дуги (а, h) существовал путь Р(а, Ь), состоящий из существенных дуг. Отметим, что, когда частичное упорядочение представляют в виде графа, обычно изображают не сам граф частичного упорядочения, а его транзитивную редукцию. Граф G(P) частичного упорядочения называют также носителем частичного порядка Р. Нетрудно заметить, что диаграмма Хассе чу-множества есть не что иное, как не- ориентированный граф, получаемый из транзитивной редукции носителя чу- множества указанным способом, расположенный на плоскости специальным образом. Неориентированный граф G''(P), получаемый из G(P) заменой дуг ребрами, называ- ется графом сравнимости для G(P). В свою очередь неориентированный граф явля- ется графом сравнимости, если существует такая ориентация его ребер, которая дела- ет результирующий орграф транзитивным. Этот процесс называется транзитивной ориентацией. « Частичный порядок называется N-свободным, если его транзитивная редукция не со- держит любых четырех вершин а, b, с, d таких, что а > Ь, с > Ь, с > d и а не сравнима cd. Такое название продиктовано тем, что вершины a, b, с, d образуют фигуру N в диаграмме частичного порядка. Говорят, что цикл [хо, Х|, . , х*_|] имеет хорду, если существует ребро, соединяющее вершины х, и xj такие, что j * i+ 1 (mod k),j * i - I (mod k). Неориентированный граф называется хордальным, если в нем не существует циклов без хорд длины больше 3. Частичный порядок называется свободным от циклов, если его носитель, рассматри- ваемый как неориентированный граф, является хордальным графом. Граф G называется интервальным графом, если он является графом пересечений множества F замкнутых интервалов на вещественной прямой Другими словами, су- ществует биекция между вершинами графа G и интервалами из множества F такая, что две вершины смежны тогда и только тогда, когда соответствующие им интервалы перекрываются. Известно, что дополнение к интервальному графу есть граф сравни-
Глава 12. Прочие граф-модели 949 мости. Отсюда следует, что на множестве вершин интервального графа можно опре- делить упорядочение, положив х < у всякий раз, когда интервал 1Х, соответствующий вершине х, целиком лежит слева от интервала 1у. Упорядочения, возникающие при таком подходе, носят название интервальных порядков. Укажем основные типы частичных порядков на множестве кортежей различной длины. Лексикографический порядок. Пусть Р— множество всех последовательностей длины п с элементами из множества Х= {1,..., п}. Тогда полагаем: (хь х2, ..., х„ ) < < (Уь У2, —>Уп) тогда и только тогда, когда такой номер к, чтох,=_у,, 1 <t < кихк<ук. Антилексикографический порядок. Пусть, как и при определении лексикографиче- ского порядка, Р— множество всех последовательностей длины п с элементами из множестваХ = {1, ..., п}. Тогда полагаем: (хь х2,..., х„) < (уьУг, —,Уп') тогда и только тогда, когда такой номер к<п, что хк > ук и х, = yh к < t < п. Доминирующий порядок. Пусть Р есть множество последовательностей ( /д) вида (щ, и2, «л, 0, 0, ...), где и, > н2 ... > пк. Тогда полагаем: {пк} < {тф тогда и только то- гда, когда / = к - 1 и все совпадают с за исключением одной пары чисел nh и одного числа тс, для которых выполняется равенство тс = па + пь. 12.2.4. Решетки, подрешетки и полурешетки Определение решетки Пусть [Р, < ] — чу-множество и пусть a,b е Р. Элемент d е Р называется наибольшей нижней границей, или пересечением, или нижней гранью элементов а и Ь (обозначе- ние: d= а л Ь), если d<a, d<buwix<aHx<b следует, что х < d. Двойственным образом определяется наименьшая верхняя граница, или объединение, или верхняя грань а и Ь, обозначаемая s = a v b. Не следует путать операции объединения и пересечения, соответственно, с операция- ми взятия наибольшего или наименьшего элемента: они совпадают там, где опреде- лены и те, и другие, но первые определены чаще. В цепях эти операции действитель- но не различаются: объединение двух элементов в цепи равно наибольшему из них, а пересечение — наименьшему. Решеткой называется чу-множество L, в котором любые два элемента х и у имеют нижнюю грань (пересечение) х л у и верхнюю грань (объединение) х v у. Заметим, что любая цепь есть решетка. Множество натуральных чисел, где х < у оз- начает, что х делит у, есть также решетка; здесь объединение х и у есть их наимень- шее общее кратное, а пересечение — их наибольший общий делитель. Пусть Р и S cz Р. Расширим операцию объединения на множество 5, определив ее как верхнюю грань 5, и операцию пересечения, определив ее как нижнюю грань 5. Если объединение S существует в Р, то его обозначают или vS, или v,eS5. Аналогично, пе- ресечение S, если оно существует, обозначается или aS, или AseSs. Решетка L называ- ется полной, если любое ее подмножество имеет в L верхнюю и нижнюю грани.
950 Часть II. Применение графов и граф-моделей Решетка иногда обозначается тройкой (Р, v, л ), где v и л — операции объединения и пересечения, определенные на Р. Мощность решетки (Р, v, л ) есть мощность чу- множества Р. Для любого множества S множество -всех подмножеств 5 частично упорядочено по включению; (2s, kJ, n) есть полная решетка. Не каждая решетка полна: так, чу- множество рациональных чисел не является полной решеткой; любая конечная ре- шетка, а также решетка конечной длины (соответствующее чу-множество есть чу- множество конечной длины) являются полными. Примеры решеток Существует несколько важных типов решеток. Приведем некоторые из них Решетка М(к) мультимножеств (множеств с повторениями) некоторого /.-элементного множества S. Ее структура определяется лишь мощностью к данного множества. На рис. 12.19 показаны решетки М(1) и М(2). Решетка В(к) всех конечных подмножеств /с-элементного множества S. Ее структура также определяется лишь мощностью к множества S. Эта решетка иначе называется булевой алгеброй ранга к. На рис. 12.20 показаны булева алгебра В(4) и изоморфная ей решетка двоичных векторов длины 4. Решетка Р(п) разбиений «-элементного множества N. Пусть л и а — два разбиения конечного множества N на блоки. Соотношение п < ст означает, что каждый блок из л целиком содержится в некотором блоке из о, или, обратно, каждый блок разбиения ст полностью распадается на блоки из л. Исходя из этих соображений, говорят, что л есть уточнение (измельчение) о, а отношение < есть отношение измельчения. Един- ственное самое грубое разбиение — это разбиение, состоящее из одного блока N, то- гда как самое тонкое разбиение — это разбиение, в котором каждый блок состоит из одного элемента. Пусть (л)— отношение эквивалентности, соответствующее разбиению л на /V. Тогда для любых разбиений л, и множества N и произвольных элементов a, b & N имеем а(л л d)b тогда и только тогда, когда а(л)£> и а(ст)Ь, а а(л v d)b тогда и только тогда, когда существуют а = м0, wb ..., w, = b такие, что м,(л)м/+1 или и,(ст)м,41 для всех /.
Гпава 12. Прочие граф-модели 951 1234 1111 0000 Рис. 12.20. Булева алгебра В(4) и соответствующая ей решетка Ясно, что с точностью до изоморфизма решетка P(/V) разбиений конечного множест- ва N зависит только от мощности N; поэтому можно просто писать Р(и). На рис. 12.21 показана решетка Р(4). Решетка Юнга имеет в качестве своих элементов последовательности а = (аь а2, ••) неотрицательных целых чисел а\ > аг >..., где а, = 0 для j > п0, а отношение порядка задано формулой (аь а2,...) S (feb b2,...) <=> а, < bj для всех i. Другая очень полезная интерпретация решетки Юнга состоит в следующем. Пусть и & N ип = п2 + ...+ nk — разбиение и в сумму натуральных чисел и, (к-разбиение числа и). Так как порядок слагаемых и, не имеет значения, то полагаем, что они запи- саны в порядке невозрастания: nt>n2> ... > пк. Ясно, что элементы (иь п2,..., пк, 0, 0,...) можно отождествить с числовыми разложениями щ + п2 + ... + пк. Значит, решетку Юнга можно рассматривать как решетку числовых разбиений со слагаемыми, упоря- доченными по величине. На рис. 12.22 показана нижняя часть решетки Юнга, где для А-разбиения + п2 + ... + пк используется обозначение ntn2...nk.
952 Часть II. Применение графов и граф-моделей Рис. 12.22. Решетка Юнга Отметим, что любому разбиению л = А}\ А2\ ...| Ак некоторого «-.элементного множе- ства на подмножества можно сопоставить числовое разбиение г(л) = п\ + п2 +...+ пк, где л, = |Л,|, 7=1, ..., к. Следовательно, отношение уточнения в Р(«) порождает неко- торое упорядочение разбиения числа rr. 'Ln, < L/л, тогда и только тогда, когда сущест- вуют л, о е Р(п), для которых л < о и т(л) = ;(сг) = D»,. Это отношение частичного порядка эквивалентно доминирующему порядку. Соот- ветствующее чу-множество обозначается D («). На рис. 12.23 изображено чу- множество 0(7). Рис. 12.23. Чу-множество 0(7) Подрешетка Подрешеткой решетки L называется подмножество X с L такое, что если a е X, be X, то a/\beXwa\/beX.
Глава 12. Прочие граф-модели 953 Подрешетка решетки сама является решеткой с теми же операциями объединения и пересечения. Пустое подмножество и любое одноэлементное подмножество также будут подрешетками. Говорят, что решетка М вкладывается в решетку L, если суще- ствует изоморфизм решеток <р (т. е. отображение <р инъективно и сохраняет операции пересечения и объединения), при котором М отображается на подрешетку решетки L. Если a < Ь в решетке L, то (замкнутым) интервалом [а, /?| называется множество всех элементов х е L, которые удовлетворяют неравенствам а < х < Ь. Любой интервал является подрешеткой. На рис. 12.24 показан интервал [ 1,360] решетки делителей. Рис. 12.24. Интервал [1, 360] решетки делителей Выпуклым подмножеством чу-множества Р называется подмножество, которое вме- сте с любыми своими элементами а, Ь, где а<Ь, содержит весь интервал [а, Ь]. Под- множество S решетки L является выпуклой подрешеткой, если для любых a, b е S будет а л b, av b <^S. Подмножество решетки L может быть решеткой относительно того же (точнее, инду- цированного) порядка, не будучи, однако, подрешеткой. Бинарные операции л и v в решетках имеют ряд важных алгебраических свойств. А. В любом чу-множестве для операгщй пересечения и объединения выполняются, если, конечно, определены входящие в них выражения, следующие законы (тож- дества): L1. Идемпотентность: х /\х = х, х v х = х. L2. Коммутативность: х /\у = у /\х, х vy =у vx.
954 Часть II. Применение графов и граф-моделей L3. Ассоциативность: х л (ул z) = (х л у) л z, X V (у V z) = (х v_y) V Z. L4. Поглощение: х л (х v у) = х v (х л у) = х. Кроме того, неравенство х < у равносильно каждому из условий х л у = х и х v у = у (совместимость). Б. Во всякой решетке операции объединения и пересечения изотонны : если у < z, то х л у < х л z и х v у < х \/ z. К. Во всякой решетке имеют место следующие неравенства дистрибутивности: -х л(у v z) > (х л у) v (х л z), -х v (у л z) < (х v у) л (х v z). Г. Элементы любой решетки удовлетворяют следующему неравенству модуляр- ности: если х < z, то х v (у л z) < (х v у) /\ z. Тождества L1—L4 полностью характеризуют решетки, а именно, имеет место утвер- ждение: Д. Любая алгебраическая система R с двумя бинарными операциями, удовлетво- ряющими тождествам L1—L4, является решеткой и обратно. Дистрибутивные решетки Решетка называется дистрибутивной, если в ней выполняется тождество L5. х л (у v z) = (х л у) v (х л z), или равносильное ему L5'. х v (у л z) = (х v у) л (х v z). Примеры недистрибутивных решеток приведены на рис. 12.25. Рис. 12.25. Примеры недистрибутивных решеток Е. Любая цепь является дистрибутивной решеткой. Решетка, двойственная к дистрибутивной решетке, дистрибутивна, и любая подре- шетка дистрибутивной решетки дистрибутивна.
Гпава 12. Прочие граф-модели 955 Ж. Если в дистрибутивной решетке для произвольного фиксированного с имеют место равенства слх = слуисух = с\/у, то х = у. Дополнением элемента а в решетке R с универсальными гранями О и I называется такой элемент х е L, что а /\х = Окаух=1 Очевидно, О и I дополнительны друг другу. Если дополнение к а существует, оно обычно обозначается через а'. В боль- шинстве решеток, например в цепях длины п (п > 2), существуют элементы без до- полнений. В решетке на рис. 12.25, в единственным таким элементом является а. Ес- ли для каждого а е R существует дополнение я'е R, то решетка называется решет- кой с дополнениями. 3. В дистрибутивной решетке с дополнениями R дополнение а' любого элемента а е R единственно. И. В любой дистрибутивной решетке множество всех элементов с дополнениями образует подрешетку. В недистрибутивной решетке на рис. 12.25, в элементы с дополнениями не образуют подрешетку. Модулярные и полумодулярные решетки Рассматривая для дистрибутивного тождества L5 случай х < z, т. е. z = х v z, мы полу- чаем самодвойственный "модулярный" закон (тождество): L6. Если х < z, то х v (у л z) = (х v у) л z. Таким образом, L6 имеет место в любой дистрибутивной решетке. Решетка называется модулярной, если в ней выполняется модулярный закон L6. Не всякая решетка модулярна. Пример немодулярной решетки приведен на рис. 12.25, б, решетка на рис. 12.25, а недистрибутивна, но модулярна. Что касается решетки Ns на рис. 12.25, б, то она является единственной немодулярной решеткой с пятью элементами. Более того, имеет место утверждение. К. Любая немодулярная решетка L содержит решетку Ns в качестве подрешетки. Следующие свойства модулярных решеток для решеток конечной длины являются необходимыми и достаточными условиями модулярности. Л. В любой модулярной решетке П если at Ьи оба элемента aub покрывают с, то a v b покрывает и a,ub\ П двойственно, если atbuc покрывает оба элемента а и Ь, то а и b оба покрыва- ют а /\Ь. Решетки конечной длины, удовлетворяющие условиям свойства 12.2.4, Л, называют- ся полумодулярными. Более точно, решетка конечной длины, удовлетворяющая пер- вому условию, называется полумодулярной сверху, а решетка конечной длины, удов- летворяющая второму условию, — полумодулярной снизу.
956 Часть II. Применение графов и граф-моделей Полурешетки Система с одной бинарной идемпотентной, коммутативной и ассоциативной операци- ей называется полурешеткой. Чу-множество Р называется /\-полурешеткой или нижней полурешеткой относитель- но бинарной операции л, если в Р любые два элемента имеют пересечение. Частич- ный порядок на элементах полурешетки вводят, полагая по определению х < у <=> о ,г Л}1 = х, х <}’ ох л) = х & х у Операцию пересечения можно распространить на произвольные непустые конечные множества, полагая х, = X] лх2 л ... лх„. 1<1<П Говорят, что полурешетка L содержит ±, если для всехх е £1 лх = 1. Единицей по- лурешетки называют элемент Т такой, что для всех хе£ Т л х = х. Всякая последова- тельность хь ... х2 элементов из L такая, что х, > х,+) для всех i > 0, называется строго убывающей цепью (с началом в Xi). Полурешетка L называется полурешеткой с обры- вающимися цепями, если все ее строго убывающие цепи конечны, и ограниченной полурешеткой, если для всякого хе£ существует такое число Ьх, что длины всех стро- го убывающих цепей с началом в х ограничены числом Ьх. Для полурешеток с обрывающимися цепями операцию пересечения можно рас- пространить на произвольные непустые, не более чем счетные множества S сле- дующим образом. Пусть S= {хь х2,...}— счетное множество элементов из £ и У„= Л х/(Л7>0)- Тогда в силу условия обрыва цепей последовательность у, >у2>... 1</<Л может содержать только конечное число различных элементов, т. е. найдется такое число т, что для всех п > т имеет место равенство у„ = ут. Определим тогда /\х=уп,. Имеет место следующее свойство: xc.S' М.Для непустых, не более чем счетных подмножеств S полурешетки с обрываю- щимися цепями Vx(xeS=>x>y)=>(/\x)>y. 12.2.5. Теорема о неподвижной точке Лусть [£,<] — чу-множество и/ g: S —> S— изотонные (см. разд. 12.2.1) функции. Справедливы следующие свойства: А. Если/, g — изотонные функции, то таковой же является их композиция fig. Таким образом, композиция сохраняет изотонность (монотонность). Теорема о неподвижной точке. Пусть f: S S— изотопная функция на чу- множестве [S, < ] с наименьшим элементом _1_ и конечной длины. Тогда наименьшей неподвижной точкой для f будет служить /*(±), где /°(х) = х,/,+|(х) =/(Л(х)) для i > G,fk(X_) и не существует j,G<j < к такого, что /'(/)
Глава 12. Прочие граф-модели 957 Алгоритм 12.1. Отыскания неподвижной точки Дано. Изотонная операция / S —> S на v-полурешетке конечной длины с нулевым элементом ± (двойственно: л-полурешетке с единичным элементом Т). Требуется. Наименьшая неподвижная точка /*(±) (двойственно: наибольшая неподвижная точка/*(Т)) с наименьшим к. Метод. проц НАИМЕНЬШАЯ НЕПОДВИЖНАЯ ТОЧКА(/)= 1. х = ±; 2. пока х / f(x) цикл х = Г(х)все 3. возврат х все Свойства операций на полурешетках Пусть [S, < ] — полурешетка. Операция/: S—♦ S называется П дистрибутивной тогда и только тогда, когда для каждых х, у е S имеет место /(х л у) = (fix) л/(у)); П непрерывной тогда и только тогда, когда для всех направленных подмножеств Тс S имеет место/(л Г) = л {/(х) | х е Т }. Непустое подмножество 7 с S называ- ется направленным тогда и только тогда, когда каждое непустое конечное под- множество в Т имеет нижнюю грань, принадлежащую Т. Теорема Хехта. Операция /на полурешетке [S, л] изотонна (монотонна) тогда и только тогда, когда для всех х, у е S имеет место fix л у) < (fix) л fiyS). 12.2.6. Кодирование частичных порядков Во многих приложениях теории частично упорядоченных множеств, таких как базы данных, искусственный интеллект, языки программирования, распределенные систе- мы и т. д., возникает проблема эффективного представления бесконтурных орграфов, частичных порядков и решеток. Глобальная проблема здесь состоит в ответе на во- прос: какие классы порядков могут быть эффективно представлены? Под эффектив- ностью здесь понимается использование минимального объема памяти, малый объем времени препроцессирования и быстрое получение ответа. В этом разделе данная проблема будет вначале рассмотрена для решеток, т. к. она служит базисом для всех дальнейших построений. Для решеток будет построено представление в виде дерева. В дополнение к введенным в разд. 12.2.4 понятиям оп- ределим некоторое количество новых. Пусть Р = [X </> ] — чу-множество. Определим для каждого элемента х е Р сле- дующие множества: Prefix) = {у е X | у <t. х}— множество предшественников х, Sucfix) = {у е X | х <р у} — множество последователей х, 1х = {у е X | у <t> х} — идеал, соответствующий х, "[х — {у е X | х </> у} — фильтр, соответствующий х.
958 Часть II. Применение графов и граф-моделей Пусть L — решетка. Элемент х е L называется v-несводимым, если х / 1 и х = }’ v z влечет х = у или х = z для всех у, z е L. Другими словами, х покрывает только один элемент, л-несводимые элементы определяются двойственно. Будем обозначать множество v-несводимых элементов L через JfL) и множество л-несводимых элемен- тов — через M(L). Обозначим через /(Р) множество антицепей в Р, упорядоченных следующим образом: А < /(!>) В тогда и только тогда, когда для всех х е А существует у е В такой, что х< /> у. Известно, что при таком упорядочении /(Р) представляет собой дистрибутивную ре- шетку. Обозначим через AMfP) подмножество /(Р), образованными антицепями в Р, максимальными по включению. Заметим, что AMfP) также решетка, но необязатель- но дистрибутивная. Пусть L— конечная дистрибутивная решетка. Известно, что L может быть реконст- руирована как решетка идеалов множеств ./(£) или MfL). Для недистрибутивной решетки нужны как v-несводимые, так и л-несводимые эле- менты. Это означает, что любая решетка L может быть охарактеризована двудольным порядком BIPfL), вычисляемым следующим образом: BIPfL) = |Л/(Л), J(£), < нщт}], где х < вп'д^ тогда и только тогда, когда х е MfL), у е JfL) и х > /,у. Решетка L может быть реконструирована как решетка AMfBIPfL)) максимальных ан- тицепей чу-множества BIPfL) Справедливо следующее утверждение. А. Пусть L —решетка Тогда L ~ AMfMfL), JfL), ^t) = AMfX, JfL), ^/г) = AMfMfL), X, >Л), где X—множество элементов L. Отсюда вытекает, что решетка может быть представлена тремя способами с по- мощью решеток максимальных антицепей. Для простоты будем использовать второй способ и с этой целью определим BIPfL) - (X, JfL), &L). Кодирование решеток деревьями В этом разделе дается представление решеток деревьями и показывается, как при этом вычисляются основные операции решетки. Пусть даны решетка L = fX, </) и сопоставленный с ней двудольный порядок BIPfL) - = fX,JfL),^L). Множество последователей (потомков) вершины х из множества X порядка BIPfL) образует код вершины х, обозначаемый codefx). Б. Функция х —» codefx) взаимно однозначна и х < /, у тогда и только тогда, когда codefx) z> codefy). В. Пусть L — решетка их,у е L, тогда codefx vу) с codefx) n codefy) и codefx лу) о codefx) о codefy). Пусть т — линейное расширение J(L); упорядочим вершины JfL) в соответствии с т. Обозначим через CODEfx) убывающую последовательность элементов в codefx) в соответствии с т. Используя эти коды, можно построить дерево рекурсивно сле- дующим образом.
Гпава 12. Прочие граф-модели 959 Начиная с корня, обозначаемого через top с code(top) = 0, определяем для рассмат- риваемой вершины х из L в качестве ее отца в дереве вершину z такую, что CODE(z) лексикографически максимален среди всех вершин, удовлетворяющих условию code(z) с: code(x). Ребро (х, у) в дереве получает метку C()DE(x) \CODE(y) и поэтому метки на пути из корня в любую вершину дерева убывают в соответствии с т. Такое дерево, обозна- чаемое T{L), называется древесным представлением L; его высота ограничена |J(Z)|, т. к. размер максимального кода ограничен J(L) и ребра помечены по крайней мере односимвольными метками (синглетонами). На рис. 12.26 приведен пример такого дерева. Линейное расширение т для J(L) имеет вид т = dceb', оно вычислено в соответ- ствии с числом предшественников вершин в B1P(L). б) X code(x) CODE(x) а bcde 1234 b cde 123 с bde 134 d bee 234 е bed 124 f be 34 g be 24 h 0 0 г) Рис. 12.26. Древесное представление решетки Пусть L = (X, Е) — решетка, заданная диаграммой Хассе (графом транзитивной ре- дукции) с |А"] = п и |Е| = т, тогда трудоемкость построения древесного представления Т(Е) имеет трудоемкость О(пт), а трудоемкость вычисления объединения и пересече- ния двух элементов в решетке равна О(Д|У(А)|), где Д есть наибольшая степень вер- шин в Т(Е), не превосходящая Щ
960 Часть II. Применение графов и граф-моделей В общем случае дерево Т(Е) не единственно (т. к. оно зависит от выбранного линей- ного расширения т). Решетка L называется симплициалъной, если ее высота равна |J(Z)| или |Л/(£)|. Дерево Т(Е) представляет собой каркас решетки L, если L — дистри- бутивная или симплициальная решетка, но в общем случае это неверно. Более того, если L дистрибутивна, то все ее древесные представления имеют ребра, помеченные синглетонами. Для симплициальных решеток известно только о сушествовании таких древесных представлений. Кодирование битовыми векторами Как было указано (см. разд. 12.3.4), булевская решетка может быть определена как [{0,1}", < ], где п— заданное целое число, а < есть произведение порядков, порож- денное порядком 0 < 1. Мы можем сопоставить с каждым элементом булевской ре- шетки подмножество целых чисел, определяемое единичными элементами битового вектора, так что два элемента сравнимы, если сопоставленное множество одного со- держит сопоставленное множество другого. С формальной точки зрения кодирование битовыми векторами порядка Р означает, что каждому элементу х е Р сопоставляется (0,1)-вектор BitVect(x) так, что объедине- ние, пересечение и достижимость могут быть определены с помощью логических операций над этими векторами. Таким образом, для всех х, е Р х <Ру тогда и только тогда, когда BitVect(y) cz BitVect(x). Практическое использование битовых векторов основано на предположении, что по- битовые операции могут быть выполнены за константное время. В настоящее время известны алгоритмы генерации битовых векторов с помощью вложения чу- множества в решетку его идеалов с последующим вложением в булевскую решетку. Битовые вектора также тесно связаны с размерностью порядка, в частности с ограни- ченной размерностью dirr^P), т. к. dim2(P) может быть интерпретировано как наи- меньшее целое t такое, что Р допускает кодирование битовыми векторами длины t. Следовательно, dim2(P) есть оптимальный размер кодирования Р битовыми вектора- ми. К сожалению, вычисление dim2(P) и, следовательно, оптимальных битовых век- торов есть Л'Р-трудная проблема. Кодирование решеток битовыми векторами Пусть L = (X, Е)— решетка. Тогда L изоморфна решетке максимальных антицепей двудольного порядка B1P(L) = (Л/(£), J(L), и может быть закодирована битовыми векторами длиной min(|AY (Z)|, |J(Z)|). При этом если L — цепь, то она может быть закодирована оптимально битовыми векторами длиной |Л/(£)| = |J(Z)| = |£| — 1. Спра- ведливо следующее свойство: Г. Если L = (X, Е) дистрибутивная или симплициальная решетка, то L может быть оптимально закодирована битовыми векторами, длина которых равна ее высоте. Из этого свойства вытекает, что вложение частичного порядка в симплициальную решетку вместо дистрибутивной достаточно для гарантирования оптимального коди- рования битовыми векторами. Для несимплициальных решеток задача кодирования может быть преобразована к проблеме вложения в симплициальную решетку мини- мальной высоты.
Гпава 12. Прочие граф-модели 961 Решетка L называется завершением Мак-Нейла порядка Р, если она является наи- меньшей решеткой, в которую Р может быть вложен. Такое вложение осуществляется отображением ср: Р —> L, где <р(х) = х. Завершение Мак-Нейла (или Дедекинда-Мак- Нейла) порядка Р обозначается DM(P). Имеет место следующее соотношение: dim2(P) = = dim2(£>A/(P)). Отсюда может быть выведено условие оптимальности для кодирова- ния битовыми векторами порядка Р. В самом деле, если DM(P) — симплициальная или дистрибутивная решетка, можно предложить следующий метод построения оп- тимального кодирования. Ленивое завершение Мак-Нейла частичного порядка Пусть Р = (X, <) — частичный порядок и DM(P) — его завершение Дедекинда-Мак- Нейла. Ясно, что каждый элемент х е Р имеет образ <р(х) е DM(P). Более того, каж- дый v-несводимый или л-несводимый элемент в DM(P) имеет прообраз в Р. Так как каждая решетка может быть характеризована, используя только v- и л-несводимые элементы, то мы можем построить древесное представление для DM(P), ограничива- ясь только элементами Р. Это означает, что все элементы, добавленные к Р, чтобы получить DM(P), не являются несводимыми элементами. Покажем теперь, как определить v-несводимые элементы в DM(P). Вначале сопоставим с Р = (X, < Р) двудольный порядок В1'(Р) = (X, Xt, £|) такой, что Xt есть копияХи (х, у) е Et тогда и только тогда, когдах е X, уg Xi и х^Ру. Введем теперь понятие редукции двудольного порядка. Пусть теперь BIP' (Р) = = (Xt, Xi, Ei) — сопоставленный с Р двудольный порядок и х е А). Тогда элемент х может быть удален из Х}, если выполнено следующее условие: Pred(x) = к = [jPred(Xi), Xi eXj. Полученный порядок называется редуцированным двудоль- /=1 ным порядком и обозначается RED(BIP'(Р)) = (X, Х2, £2). Индуцированный порядок v-несводимых элементов из DM(P) задается следующим свойством: Д. Пусть Р = (X, Е) — чу-множество и пусть RED(BIP ’ (Р)) = (X, Хъ £2) — его ре- дукция. Тогда множество {Pred(x), х е Х2 из RED(B1P '(Р))}, упорядоченное по вклю- чению, изоморфно множеству J(DM(P)). Двойственный результат можно получить, если использовать редукцию А1 вместо А). Используя свойство 12.2.6, Д, двойственное ему, и свойство 12.2.6, А, получаем, что DM(P) = АМ(Х, Х2, ». Теперь множество v-несводимых элементов в DM(P) есть Х2 и X есть подмножество элементов DM(P). Рассмотрим, как можно сопоставить с DM(P) дерево, содержащее только элементы из Р. Ясно, что Р есть подпорядок DM(P). Это означает, что если DM(P) = (У, U), тоXК Как и для решеток, последователи элементов из А" в RED(BIP‘(P)) соответствуют их кодам. Вычислим линейное расширение для {Pred(x), с },х е А2 и отсортируем коды элементов из X в соответствии с этим расширением. Как следствие, можно найти 31 Зак. 202
962 Часть II. Применение графов и граф-моделей поддерево для DM(P). Но в общем случае мы должны для сохранения структуры де- рева ввести некоторые фиктивные вершины. Пусть х, у g Р такие, что code(x) n codefy) = code * 0 и для всех i g code(x), j g codefy), к g code имеем i < к и j < к. Если не существует z g Р такого, что codefz) = code, то мы создадим фиктивную вершину z с этим кодом. Например, эта вершина z может изображать наименьшую верхнюю грань элементов х и у в DM(P). Заметим, число создаваемых таким путем фиктивных вершин не превышает |А]. Требуемое дерево есть поддерево решетки DMfP), содержащее не более 2|Л) вершин. Это представление DM(P) в виде поддерева может иметь много применений. Напри- мер, если Р есть корона, то DM(P) имеет размер 2|/>|; так что нельзя вычислить DM(P) целиком. Таким образом, используем это поддерево и завершаем его, если это нужно во время исполнения программы. Это означает, что если мы хотим вычислить наи- меньшую верхнюю границу элементов х и у, мы проверяем, есть ли такая вершина; в противном случае мы добавляем новую вершину к дереву. Этот метод соответству- ет ленивому завершению Р. Более того, кодирование битовыми векторами содержит- ся в этом дереве. Кроме того, в некоторых приложениях программистам нужен только порядок между Р и DM(P)', т. е. они в самом деле добавляют вершины, которые обладают некоторой семантикой в конкретном применении. В данном разделе были рассмотрены два представления решеток. Первое, основанное на деревьях, обеспечивает легкое вычисление достижимости, объединения и пересе- чения. Второе, основанное на кодировании битовыми векторами, обеспечивает вы- числение достижимости за время 0(1). 12.2.7. Прозрачные частичные порядки и их применения Прозрачность (transparency) частичного порядка представляет собой новую концеп- цию, ориентированную на решение проблемы мониторинга параллельных систем и представляющую минимальные требования к монитору исполнения для уменьшения его взаимовлияния с поведением целевых систем и, следовательно, изменения этого поведения. Монитор исполнения, удовлетворяющий указанным требованиям, прозра- чен по отношению к частичному порядку, порождаемому появлением параллельных событий при исполнении целевой системы. В качестве объектного языка выбран язык Ада. Предлагаемая абстрактная модель основана на теории решеток и служит для представления историй исполнения параллельных программ в терминах взаимодейст- вия заданий. Концепция прозрачности частичного порядка вводится формально на основе этой модели. Заметим, что мониторинг поведения вычислительной системы (например, исполняе- мая спецификация, программа или группа программ в распределенной системе) есть фундаментальная техника, используемая при разработке программного обеспечения и его сопровождении, т. к. он поддерживает состояние трассировки, тестирования, от- ладки, опенки производительности, настройки и динамической реконфигурации сис-
Гпава 12. Прочие граф-модели 963 темы. Таким образом, мониторинг играет фундаментальную роль в разработке и со- провождении программного обеспечения (ПО) и поэтому монитор исполнения явля- ется в общем случае совершенно необходимой компонентой окружения для разра- ботки ПО. При мониторинге параллельных (включая распределенные) систем любой механизм будет взаимодействовать с исполнением системы и может даже изменить ее поведе- ние. Это возникает в силу того, что поведение системы в общем случае зависит от прогонки программы. Уменьшение степени такого взаимодействия представляет со- бой важную проблему, называемую проблемой точного мониторинга. Однако к на- стоящему времени не известно ее общего решения. Более того, невозможно пол- ностью устранить это взаимодействие. Поэтому все, что можно сделать, — это разра- ботать такой монитор исполнения, который бы минимально взаимодействовал с це- левой системой и по возможности не изменял ее поведения. Другими словами, нужны явно и точно сформулированные требования к монитору исполнения, с по- мощью которого можно было бы измерять точность поведения системы при монито- ринге. Мониторинг параллельных систем Мониторинг программы включает в себя сбор, запись, анализ и отображение инфор- мации о поведении программы. Примитивными объектами для мониторинга служат события, происходящие при исполнении программы. В последовательной программе события — это либо передачи управления, либо дос- туп к переменной, либо операция ввода/вывода. С другой стороны, в параллельной программе к событиям могут относиться не только локальные действия внутри про- цесса, но также создание и ликвидация процесса или коммуникация и/или синхрони- зация между процессами. В первом случае говорят о последовательном событии, во втором — о параллельном событии. Целевой программой называется входной текст программы, подлежащей мониторин- гу. Язык, на котором написана целевая программа, будет называться целевым языком программирования. Точка извлечения информации— это то место в целевой про- грамме, где при исполнении программы происходит событие, имеющее семантиче- скую интерпретацию на уровне целевого языка программирования. Сенсор есть фрагмент кода, который вводится в точку извлечения информации целевой програм- мы для того, чтобы собрать информацию о событии, произошедшем в точке. Сенсор может быть кодом целевого языка программирования или кодом объектного языка. Сенсоры первого вида вводятся в целевую программу, сенсоры второго вида — в объектную программу, получаемую при компилировании целевой программы. Про- грамма, получаемая из целевой вводом сенсоров, называется субъектной програм- мой. Монитор времени прогона — это программа для связи с сенсорами субъектной программы и для сбора информации о событиях, возникающих в целевой программе, соответствующей субъектной программе. Монитор исполнения — это системная про- грамма, которая вставляет сенсоры в целевую программу, исполняет субъектную про- грамму, собирает, записывает, анализирует и отображает информацию о поведении целевой программы. Говорят, что монитор исполнения работает с исходной про-
964 Часть II. Применение графов и граф-моделей граммой, если сенсоры, вставленные в нее, представляют собой фрагменты кода на целевом языке программирования; в противном случае говорят, что монитор испол- нения работает с объектной программой. В качестве механизма сбора информации при мониторинге могут быть использованы трассировка (tracing) или опрос (sampling). При трассировке информация, собирае- мая сенсорами, посылается в монитор времени прогона всякий раз, когда в субъект- ной программе происходит событие. При опросе информация, собираемая сенсорами, посылается в монитор времени прогона только в том случае, если монитор запро- сит ее. В целом мониторинг может рассматриваться как трехступенчатый процесс. 1. Предобработка. Монитор исполнения генерирует для целевой программы соот- ветствующую субъектную программу. 2. Мониторинг исполнения. Монитор исполнения исполняет субъектную программу и потом собирает и записывает информацию о поведении целевой программы. 3, Постобработка. Монитор исполнения анализирует и отображает собранную ин- формацию. Решетка как модель историй исполнения параллельных Ада-программ Для формального обсуждения проблемы точного мониторинга совершенно необхо- дима абстрактная модель поведения целевой программы. При конструировании фор- мальной модели физической системы хорошая стратегия заключается в определении базовых понятий в терминах таких атрибутов системы, которые были бы прямо или косвенно наблюдаемы и измеряемы. Для моделирования поведения параллельных Ада-программ на уровне задач определяются и используются в качестве примитивов события, связанные с задачами. Неформально, событие в параллельной Ада-про- грамме на уровне задач есть атомарное действие, появление которого может быть замечено на уровне исходного кода. Поведение на уровне задач будет рассматривать- ся как некоторый поток задач-событий. Таким образом, состояние задачи, которое описывает, что эта задача делает, может быть определено с помощью двух тесно свя- занных задач-событий. При таком подходе можно сосредоточиться только на взаимо- действии задач, не обращая внимания на детали внутренней кухни задач. Основной механизм для межзадачных коммуникаций в Аде есть рандеву. Это пред- полагает, что задания всех Ада-программ, рассматриваемых в этом разделе, сообща- ются между собой, используя только рандеву даже тогда, когда задания могут сооб- щаться между собой, используя общие переменные. Таким образом, поведение такой Ада-программы определяется заданным входом и последовательностью синхрониза- ций и коммуникаций между заданиями. С другой стороны, не делается никаких предположений относительно темпа (rate) исполнения параллельно исполняемых заданий, исключая предположение о том, что темпы всех заданий положительны, т. к. было бы желательно понимать поведение параллельной Ада-программы на уровне заданий в терминах взаимодействия между компонентами заданий безотносительно к способу исполнения заданий в определен- ном темпе.
Гпава 12. Прочие граф-модели 965 Главная программа Ада-программы ведет себя так, как если бы она была вызвана заданием некоторого окружения. Это задание будет в дальнейшем называться глав- ным заданием. Предполагается, что главное задание имеет виртуальную декларатив- ную часть, которая включает описания главной программной процедуры и все биб- лиотечные модули, нужные для главной программы. Что касается атомарных действий при выполнении заданий, то в Ада-программе мо- гут быть выделены 33 вида таких действий, каждое из которых специфицируется сво- им именем. Событие е, связанное с заданием (или просто событие), формально определяется как набор е = (Г, N, То, Е, Me, В, Ma, t), где Т есть уникальное имя задания, где появляет- ся е; N есть имя события е (одно из 33); т. е. либо ± (обозначающее "не определено"), либо уникальное имя задания, которое создается, вызывается или удаляется заданием Т\ Е есть либо ±, либо множество уникальных имен элементов, которые могут быть использованы для связи Т с другими заданиями; Me есть либо ±, либо множество со- общений, посылаемых между Т и другим заданием во время их рандеву; В есть либо ±, либо уникальное имя подпрограммы, вызываемой Т, или блочный оператор, ис- полняемый Г; Ma есть либо ±, либо уникальное имя мастера, который непосредст- венно создает Г; t есть время появления события (это время может быть физическим или виртуальным в зависимости от реализации Ады). Пространство событгш TES(P, Г), создаваемое исполнением Ада-программы Р сданным входом /, есть множество всех событий, произошедших во время испол- нения. Для любого пространства событий TES(P, Г) можно определить частичный порядок в соответствии с семантикой заданий в Аде. Этот частичный порядок может рассмат- риваться как минимальное ограничение на порядок появления событий в течение ис- полнения программы Р с входными данными 1. Он определяется входом I и семанти- кой заданий в Р. Например, задание может быть активировано только после начала исполнения его мастера и должно быть завершено до завершения работы мастера, но различные задания, зависящие от этого мастера, могут начинать свое исполнение (в частности, их активацию) в любом порядке. На данном пространстве событий TES(P, Г) = {е,}, е,= (7), N„To„ Е„ Me,, В„ Ma„t,) определим бинарное отношение DS следующим образом. Для любых двух элементов еь е2 е TES(P, Г) положим (еь е2) g DS тогда и только тогда, когда е2 происходит по- сле появления е1 и, кроме того, и е2 удовлетворяют одному из следующих условий: □ Т\ = Т2 и е2 происходит непосредственно после появления е^, П Т\ * Т2 и е2 и С) выполняют синхронизацию между Т2 и такую, как синхрониза- ция относительно заданного подмножества задач-событий. Если (в), е2) е DS, то е2 называется непосредственным потомком et. Справедливы следующие утверждения: А. Для любого TES(P, Г) рефлексивно-транзитивное замыкание отношения DS на TES(P, Г), называемое частичным порядком заданий и обозначаемое <тро, есть час- тичный порядок на TES(P, Г), другими словами, [TES(P, Г), <тю] есть чу-множество.
966 Часть II. Применение графов и граф-моделей Б. Любое чу-множество [TES(P, Г), <?/ад] имеет наименьший элемент (MAIN_TASK, Activationstart, ±, ±, ±, ±, ±, tA), где MA1N_TASK есть идентификатор главного за- дания в Р, tA — время начала активации главного задания', если [TES(P, Г), ко- нечно, то оно имеет также наибольший элемент (MAIN_TASK, Termination, ±, ±, ±, ±, ±, /у), где 1т есть время завершения работы главного задания В. В любом чу-множестве [TES(P, Г), </го] подмножество, все элементы которого один и тот же идентификатор задания, есть цепь. Г. Любое [TES(P, Г), <•//•«] есть полурешетка относительно операции пересечения', более того, если [TES(P, Г), <7ТО] конечно, то оно не только решетка, но даже пол- ная решетка. Решетка [ZES^/5, Г), </7yJ называется решеткой динамической структуры программы Р со входом I. Решетки динамической структуры могут рассматриваться как абст- рактная модель историй исполнения Ада-программ в терминах взаимодействия зада- ний. Эта абстрактная модель носит название решеточной модели. Она дает базу для формального обсуждения проблемы точного мониторинга параллельных Ада-про- грамм. Пусть (£ь < J и (Еу, - 2) — Две полурешетки относительно пересечения. Отображение Т: (£j, < ]) —> (£2, 5 2) называется ^-гомоморфизмом, если *Р(а л Ь) = 'Р(а) л У¥(Ь) для любых a, b е L\. л-гомоморфизм называется л— изоморфизмом, если он взаимно однозначен и сюръективен (т. е. является отображением на все множество). Если для двух решеток динамической структуры [TES(P, Ту, <7/>о] и [TES(P, Г)2, ^тро] существует л-изоморфизм Т: [TES(P, Гу, < 77><J —> [TES(P, Г)2, то], при котором для любого элемента (7), Ni, То\, Е\, Ме\, В\, Ма\, у) Л. TES(P, Гу существует ^((Т), Nt, То\, Е\, Мв{, Bi, Ма\, t\)) = (Т2, N2, То2, Е2, Ме2, В2, Ма2, t2), такое, что Т\ = Т2, N\ = N2, Toi = То2, Ei = Е2, Mei ~ Ме2, Bi = В2, Mat = Ма2, то решетки [TESfP, I)i, <уро] и [TES(P, Г)2, <7/>о] называются эквивалентными по динамической структуре (обо- значение [TES(P, I)i, <77>о] = [TES(P, Г)2, <7/>о])- Ясно, что для любой параллельной Ада-программы Р и любого входа 1 отношение = на множестве решеток динамической структуры, создаваемом повторными исполне- ниями Р с входом /, есть отношение эквивалентности. Поэтому говоря об элементе чу-множества \TES(P, I), £?т>о], имеют в виду соответствующий класс эквивалент- ности. Прозрачность частичного порядка Во время мониторинга Ада-программы можно наблюдать поведение субъектной про- граммы. Это необязательно полностью эквивалентно исходному поведению (т. е. без мониторинга) целевой программы из-за влияния мониторинга. Ясно, что точность поведения программы, производимого мониторингом, зависит от некоторой прозрач- ности монитора исполнения по отношению к поведению целевой программы при на- личии мониторинга. Из-за влияния действий при мониторинге невозможно сделать монитор исполнения полностью прозрачным для исходного поведения целевой про- граммы. Однако возможно сделать монитор исполнения прозрачным для части ис-
Гпава 12. Прочие граф-модели 967 ходного поведения целевой программы. Другими словами, для того чтобы осущест- вить аккуратный мониторинг целевой программы, действия монитора не должны из- менять поведения никакой интересующей части программы. В соответствии с раз- личными целями мы можем определить различные прозрачности для мониторов ис- полнения. Наиболее слабой прозрачностью является "прозрачность частичного порядка". Основная идея концепции прозрачности частичного порядка — сделать монитор ис- полнения прозрачным для частичного порядка относительно появлений задач- событий во время исполнения целевой программы. Обсуждение этого вопроса опира- ется на решеточную модель историй исполнения параллельных Ада-программ. Суть его заключается в обсуждении соответствия между историями исполнения целевой программы и субъектной программы в терминах абстрактных алгебраических струк- тур их решеток динамической структуры. Пусть (51, <!) и (52, <2) — два чу-множества. Отображение : 5j —> 52 называется порядковым гомоморфизмом, если оно изотонно (сохраняющее порядок). Отображение 'Р : 5, —> 52 называется консервативным гомоморфизмом или консер- вативным отображением, если оно удовлетворяет следующему условию: для любых Si, s2 е 51 еслии s2 несравнимы относительно <ь то 'P(.vi) и несравнимы отно- сительно <2. Отображение *Р : 5] —> 52 называется гомоморфизмом частичного порядка или ото- бражением, сохраняющем частичный порядок, тогда и только тогда, когда оно одно- временно и порядковый, и консервативный гомоморфизм. Монитор исполнения называется прозрачным относительно частичного порядка для целевых программ, если он удовлетворяет следующим двум условиям для любого [7Е5(Р, Г), <тро], где Ф(Р) обозначает субъектную программу для Р: Т1. Существуют [7Е5(Ф(Р), Г), <уро] и гомоморфизм частичного порядка Т : [TES(P, Г), <1РО\ -> [7Е5(Ф(Р), D, <тро1 Т2. Если для любого элемента (Т), Nh То\, Ех, Ме\, В}, Mai, ti) е [TES(P, Г), <jm] существует ^((7), М, То\, Е\, Ме\, В\, Мах, tx)) = (Т2, N2, То2, Е2, Ме2, В2, Ма2, t2), то Т\ = Т2, = TV2, То\ = То2, Е\ = Е2, Ме\ = Ме2, В\ = В2, Ма\ = Ма2. Заметим, что определение прозрачности частичного порядка требует, чтобы монитор исполнения сохранял бы не только временной и/или причинный порядок среди па- раллельных событий целевой программы, но также и несравнимость событий относи- тельно временного и/или причинного порядка. Это важное свойство монитора испол- нения, т. к. оно гарантирует, что при мониторинге могут быть наблюдаемы все воз- можные поведения целевой программы. Если монитор исполнения для параллельных Ада-программ обладает прозрачностью частичного порядка, то он сохраняет тот же самый частичный порядок заданий < ТРО в поведении субъектной программы, что и в исходном поведении целевой програм- мы. В результате любой возможный частичный порядок заданий в целевой програм-
968 Часть II. Применение графов и граф-моделей ме может встретиться в субъектной программе. Если монитор исполнения не облада- ет свойством прозрачности частичного порядка, то он не может сохранить тот же частичный порядок заданий <1Ю в субъектной программе, что и исходном поведении целевой программы. В результате только часть возможных частичных порядков в целевой программе может встретиться в субъектной программе. Поясним, как сделать монитор исполнения, работающий на основе трансформацион- ного подхода к исходной программе и удовлетворяющий прозрачности частичного порядка. Определим, пользуясь решеточной моделью, отношение эквивалентности между целевой Ада-программой Р и преобразованной программой Ф(Р) относитель- но абстрактной алгебраической структуры их решеток динамической структуры. Если программное преобразование Ф гарантирует, что существует изоморфизм между каждой решеткой динамической структуры исходной программы Р и подрешеткой соответствующей решетки динамической структуры преобразованной программы Ф(Р), то частичный порядок заданий полностью сохраняется этим преобразованием. Таким образом, если программное преобразование, используемое в мониторе испол- нения для параллельных Ада-программ, имеет это свойство, то монитор прозрачен относительно частичного порядка для целевых программ. Будем рассматривать преобразования Ада-программ (в Ада-программу) как частич- ное отображение на множестве Ада-программ и специфицировать его с помощью множества правил преобразования программ. Каждое такое правило есть также час- тичное отображение на множестве Ада-программ. Будем записывать это преобразо- вание как Ф : P(Ada) —P(Ada), где P(Ada) есть множество Ада-программ и R — множество правил преобразования Ада-программ. Пусть Т : (£ь <i) —> (L2, <2) — биекция между двумя л-полурешетками. Справедливо свойство: Д. Т есть гомоморфизм частичного порядка тогда и только тогда, когда он явля- ется г-изоморфизмом. Программное преобразование Ф : P(Ada) —>«P(Ada) называется эквивалентным пре- образованием для динамических структур, если для любой решетки [TES(P, Г), <тро] любой программы Р из P(Ada) с любым данным входом 1 оно удовлетворяет сле- дующим трем условиям: ТЗ. Существуют [7’£5(Ф(Р), /), <//>о] и л-гомоморфизм Т: [TES(P, Г), < Гро] —> [TES^P, Г), < 7го1. Т4. Т есть л-изоморфизм из [TES(P, Г), <7ТО] в [X¥(TES(P, Г)), <ц>о]- Т5. Если для любого элемента (J\, Ni, То\, Е}, Ме}, В\, Ма}, t}) е [TES(P, Г), <j/<o] су- ществует ^((Гь Ni, То\, Ei, Mei, Bi, Ма}, ti)) = (Т2, N2, То2, Е2, Ме2, В2, Ма2, t2), то 7\ = Т2, Ni = N2, Toi = То2, Ех = Е2, Met = Ме2, Bi = В2, Mat = Ма2. Эквивалентное преобразование для динамических структур Ф : P(Ada) —>к P(Ada) сохраняет задачи-события исходной программы Р и частичный порядок заданий <гю в поведении преобразованной программы Ф(Р).
Гпава 12. Прочие граф-модели 969 Пусть Ф : P(Ada) —>/?P(Ada)— программное преобразование. Правила преобразова- ния программ из R называются суперпозируемыми, если они удовлетворяют следую- щему условию: для любой Р из P(Ada) существует последовательность индексов 1\,..., i„ такая, что уравнение Ф(Р) = (...(г (Р))...) верно, когда rke R,k= it,..., i„. Е. Если ! : (/.(, <i) —> (Z.?, < 2) и (/-?> 2) —> (£3, з) — два л-гомоморфизма, то гос композиция 4V4'i: (£(, < t) —> (£3, < 3) — также /\-го.моморфизм. Ж. Пусть Ф : P(Add) —P(Ada)— программное преобразование. Если R содержит только суперпозируемые правила программных преобразований и любое правило г из R является 'эквивалентным преобразованием для динамических сгпруктур, то Ф также является эквивалентным преобразованием для динамических структур. Свойство Ж означает, что проблема эквивалентности для динамических структур программных преобразований может быть сведена к проблеме л-изоморфизма каж- дого трансформационного правила программного преобразования. В общем случае последняя решается легче первой, т. к. при этом исследуются только локальные свой- ства целевых программ. Поэтому при создании монитора исполнения, работающего на основе преобразования программ, чтобы добиться прозрачности частичного по- рядка для целевых программ, необходимо сделать две вещи. Первое, нужно так кон- струировать правила преобразования программ, чтобы они были суперпозируемыми и удовлетворяли требованиям мониторинга для конкретного монитора. Второе, нуж- но проверять, является или нет каждое правило преобразования программ эквива- лентным преобразованием для динамических структур. При этом не утверждается, что монитор исполнения полностью устраняет взаимовлияния действий мониторинга, но зато показано, что можно разработать свободный от взаимовлияния монитор ис- полнения в смысле прозрачности частичного порядка. Как показывает практика, прозрачность частичного порядка есть существенное тре- бование для мониторинга параллельных программ. Если монитор исполнения не мо- жет сохранить тот же самый временной и/или причинный порядок среди параллель- ных событий целевой программы, то он серьезно ограничивает поведение целевой программы при мониторинге и приведет к ситуации, при которой некоторое поведе- ние целевой программы никогда не будет наблюдаться при мониторинге. 12.2.8. Чу-множества и модели параллельных программ и процессов Частично упорядоченные множества рассматриваются как формальный аппарат для представления поведения параллельных систем. Пусть имеется частично упорядоченное множество PS = (X, <), где X— множество (непустое) и =/ сА’хЛ'— частичный порядок, называемый отношением причинной зависимости. PS = (X, =С) описывает процесс функционирования параллельной системы, в котором X представляет множество реализаций событий и отношение < обозначает причин-
970 Часть II. Применение графов и граф-моделей ную зависимость между реализациями событий, т. е. если у е X причинно зависит от х е X (х < у), тогда либо х совпадает с у (х = у), либо х происходит раньше, чем у (х< у) в процессе, описываемом PS. Для графического представления PS обычно используется орграф. Множество X со- ответствует множеству вершин графа, и отношение < является транзитивным замы- канием отношения, которое задается дугами графа. В качестве примера рассмотрим PS = (X, <), изображенное на рис. 12.27, гдеХ= {xt, х2, х3, х4}; Х| < хь xt < х2; < х3, jq < х4, х2 < х2, х3 < х3, х3 < х4 Л'4 < х4. Рис. 12.27. Частично упорядоченное множество X = {x-i, х2, хз, х4} Вводится ряд дополнительных отношений на элементах PS = (X, С): Д id = {(х,х) I х е X}; Д < = <\id; Д // = (< o>U id); Д <2 с < (транзитивность); Д < = -< \ -<2 (непосредственная причинная зависимость), □ *х = {у е Х\у < х}, х’ = {у е X I х <у} (непосредственное соседство); Д -= (X кХ) \ (-< и >- U id) (параллелизм); Д со = - U id). Для частично упорядоченного множества, изображенного на рис. 12.27: Д л'| idxi, х2 idх2, х3 id х3, х4 id х4; П Х| < х2, jq < х3, х3 < х4; Л х2 — х3, х3 х2^ х2 — х4, х4^ х2; Л X! = 0,х2 = {х|},х3 = {Х|}, х4 = {х3}; □ Х| = {i2}, х2 = 0, х3 = {х4}, х4 = 0. Пусть PS = (X, <) — чу-множество. Тогда: Д LcX(L *0) — li-множество, если Vx, у е L ° х Uy, L — li-сечение, если L — мак- симальное множество относительно li. Ll(PS) будет обозначать множество всех ZZ-сечений в PS;
Гпава 12. Прочие граф-модели 971 П С с X (С эьО) — со-множество, если Vx, у е С ° х со у, С — со-сечение, если С — максимальное множество относительно со. CO(PS) будет обозначать множество всех co-сечений в PS. Для примера рассмотрим чу-множество, изображенное на рис. 12.28, где: П {zi, л'з} — конечное со-сечение; П {zb z2, z3} — со-множество, но не со-сечение; □ {z,: 1 < i} — бесконечное со-сечение; П {хь х2, Z|, у2, уч} — конечное //-сечение; □ {х;: 1 < /} U yt I 1 < i — бесконечное //-сечение; □ {х/: 1 < /} — //-множество, но не //-сечение. Рис. 12.28. Дополнительные отношения на элементах чу-множества /./-множества представляют элементы множествах которые реализуются последова- тельно, //-сечения могут быть рассмотрены как последовательные подпроцессы про- цесса, описанного посредством чу-множества. Со-множества соответствуют множествам параллельных реализаций событий, со- сечения представляют максимальные множества событий, которые могут произойти параллельно. 12.3. Сети Петри Сети Петри — одна из наиболее популярных моделей параллельных систем, исполь- зуемых как для теоретических исследований, так и практических применений в раз- личных областях. Они используются для моделирования распределенных баз данных и операционных систем, архитектур вычислительных машин, систем и сетей, систем программного обеспечения, протоколов коммуникаций, семантики параллельных языков, систем с элементами искусственного интеллекта и т. д. Модели сетей Петри играют такую же важную роль в изучении параллельных систем, что и конечные ав- томаты для последовательных систем. К достоинствам сетей Петри относятся их на- глядное графическое представление и возможность автоматического анализа их свойств.
972 Часть II. Применение графов и граф-моделей 12.3.1. События и условия Среди большого числа понятий, которые возникли и исследуются в кибернетике и информатике, одним из наиболее обших является понятие дискретной динамической системы. Примерами дискретных систем могут служить электронно-вычислительные машины (ЭВМ), их элементы и устройства, сети ЭВМ, программы и операционные системы, системы сбора и автоматической обработки цифровой информации, систе- мы автоматического управления объектами и процессами, производственные систе- мы дискретного характера, такие как сборочные линии и цеха, социально-экономи- ческие структуры и т. п. В случае систем с параллелизмом и тогда, когда нас интересует не только и не столь- ко функция, реализуемая системой, а ее структурные характеристики и свойства, мо- дель системы должна быть структурно подобна самой системе. Это означает, что мо- дель можно строить по частям, как и систему. Глобальные функции и понятия могут определяться на основе локальных, соответствующих компонентам, подсистемам и подпроцессам; связи и отношения между фрагментами модели подобны связям и от- ношениям между фрагментами системы. Наконец, немаловажным фактором является возможность представления моделей систем в форме, удобной и эффективной для обработки их с помощью ЭВМ. Первый шаг на пути к построению модели дискретной системы — это абстрагирова- ние от конкретных физических и функциональных особенностей ее компонентов. Компоненты системы и их действия представляются абстрактными событиями, како- выми могут быть, например, исполнение оператора программы, переход триггера из состояния в состояние, прерывание в операционной системе, операция станка или конвейерной линии, завершение этапа проекта и т. п. Событие может произойти (реализоваться) один раз, повториться многократно, по- рождая конкретные действия (реализации события), или не произойти ни разу. Сово- купность действий, возникающих как реализации событий при функционировании дискретной системы, образует процесс, порождаемый этой системой. В общем случае одна и та же система может функционировать в одних и тех же условиях по-разному, порождая некоторое множество процессов, т. е. функционировать недетерминиро- вано. Реальная система функционирует во времени, события происходят в некоторые мо- менты времени и длятся некоторое время. В синхронных моделях дискретных систем события явно привязаны к определенным моментам или интервалам времени, в кото- рые происходит одновременное изменение всех компонентов системы, трактуемое как изменение общего состояния системы. Смена состояний в них происходит после- довательно. Отказ от тактированных последовательностей изменений состояний при- водит к так называемым асинхронным моделям, которые ориентированы на модели- рование "неалгоритмических" параллельных систем с недетерминированным поведе- нием и в которых вместо времени и временных связей используются причинно- следственные связи между событиями.
Гпава 12. Прочие граф-модели 973 Если возникает необходимость в асинхронной модели осуществить привязку ко вре- мени, то моменты или интервалы времени можно представлять как события. Таким образом, существенно синхронные системы могут описываться в терминах асинхрон- ных моделей, к которым относятся и сети Петри. Отказ от времени приводит к тому, что события в асинхронной модели рассматрива- ются либо как элементарные (неделимые, "мгновенные"), либо как составные, имею- щие некоторую внутреннюю структуру, образованную из подсобытий. Взаимодейст- вие событий в больших асинхронных системах имеет, как правило, сложную динами- ческую структуру, которую удобно описывать не через непосредственные связи между событиями, а с помощью тех ситуаций, при которых разные события могут реализовываться. При этом глобальные ситуации в системе формируются с помощью локальных операций, называемых условиями реализации событий. Условие имеет емкость: условие не выполнено (емкость равна 0), условие выполнено (емкость равна 1), условие выполнено с н-кратным запасом (емкость равна п, где п— целое положительное число). Условие соответствует таким ситуациям в моделируе- мой системе, как наличие данных для операции в программе, необходимое состояние некоторого регистра в устройстве ЭВМ, наличие деталей на конвейере и т. п. Так как события являются действиями, то они могут происходить. Для того чтобы событие произошло, необходимо выполнение соответствующих условий. Эти условия называются предусловиями события. Возникновение события может вызвать нару- шение предусловий и может привести к выполнению других условий, постусловий. События взаимодействуют с условиями, а условия — с событиями. В сетях Петри события и условия представлены абстрактными символами из двух непересекающих- ся алфавитов, называемых соответственно множеством переходов и множеством мест. 12.3.2. Определение сети Петри Прежде чем формально определить понятие сети Петри, введем некоторые обозначе- ния и определения. Будем считать, что арифметические операции распространены на векторы как поком- понентные операции. Например, К + L = (kt + l}, к2 +12, kr+ I,), где А"= (kt, к2,..., Аг) и L = (/|, 12,..., /г). Для векторов также определим следующие операции отношения: □ К= L, если к, = I, для всех /; □ К < L, если к, < /, для всех г, П K<L, если К < L и существует такое /, что к, < 1>. Сетью будем называть тройку (P,T,F), где: ПР — непустое множество элементов сети, называемых местами', □ Т— непустое множество элементов сети, называемых переходами', □ F с РхТС ТхР — отношение инцидентности, сопоставляющее каждому эле- менту сети х е X = Р и Т множество его входных элементов "х - {ye X: yFx} и
974 Часть II. Применение графов и граф-моделей множество его выходных элементов х' = {у е X: xFy}, для которых выполнены следующие три условия: • множества мест и переходов не пересекаются, т. е. Р п Т= 0; • любой элемент сети инцидентен хотя бы одному элементу другого типа, т. е. для любогохеРиТ существует такой у е Р u Т, что xFy или yFx; • сеть не содержит пары мест, у которых совпадают множества входных и вы- ходных переходов, т. е. ’р\ *р2 или р' Ф р2' для любыхрх,р2 е Р. Сеть конечна, если конечно множество ее элементов Х= Р \jT. Графическим представлением сети служит двудольный ориентированный граф (в общем случае бесконечный) с двумя типами вершин; вершины-места изображают- ся кружочками, вершины-переходы — барьерами (а также прямоугольниками или квадратами, если переходы являются неэлементарными объектами). Из вершины х в вершину у ведет дуга, если и только если xFy. На основе понятия сети, которая описывает только статическую топологию модели- руемого процесса или системы, вводятся динамические сетевые структуры, в которых местам приписываются специальные разметки, моделирующие выполнение условия, и с сетью связывается понятие ее функционирования, изменяющего эти разметки (ус- ловия) в результате так называемых срабатываний переходов. К таким динамическим сетям относятся сети Петри, их различные варианты, обобщения и частные случаи. Разметка (или маркировка) сети — это функция М: Р —> N, которая сопоставляет каждому месту р е Р некоторое неотрицательное целое число М(р) — разметку мес- та р. В графическом представлении сети разметка местар изображается помещением в вершину-кружок числа Мй(р) или, если это число невелико, соответствующего чис- ла точек (фишек). Сеть Петри — это набор W= (Р, Т, F, W, Мо), где: П (Р, Т, F) — конечная сеть; □ Мо — начальная разметка сети; □ W— функция кратности дуг. Функция IV сопоставляет каждой дуге и е F поло- жительное целое число и^= IV(u) — так называемую кратность дуги и. В графическом представлении сети N кратность и^> 1 дуги и отмечается либо чис- лом nw, которое выписывается рядом с изображением дуги и, либо пучком из nw кратных дуг, соединяющих соответствующие элементы сети. Кратность дуги, равная I, при изображении сети Петри никак не отмечается. Сеть Петри N, в которой РК(у) =• 1 для всех дугу е F, называется ординарной. Функционирование сети Петри N описывается формально с помощью множества по- следовательностей срабатываний и множества достижимых в сети разметок. Эти по- нятия определяются через правила срабатывания переходов сети. Если предположить, что все места сети N строго упорядочены каким-либо образом, т. е. Р = (рх, ...,р^, то разметку М сети (в том числе начальную разметку) можно за- дать как вектор чисел М= (ть ..., т„) такой, что w, = М(р,) для любого i, I < i < п.
Гпава 12. Прочие граф-модели 975 Если Р'= { р^, } — подмножество мест из Р, то условимся через М(Р') обо- значать множество разметок мест {М(р^ ), Л/( )}. Если Р'представить как век- тор Р' = (р^, Pit), то MfP') обозначает вектор (Л/( ),.... М(р1к )), называемый проекцией разметки М на Р'. На основе отношения инцидентности F и функции кратности дуг W можно ввести функцию инцидентности F: Р х T\J Т х Р —> такую, что F(x, у) = 0, если -i(xFy), и F(x, у) = lF(x, у) в остальных случаях. Если места сети упорядочены, то можно каждому переходу t сопоставить два целочисленных вектора *F(Z) = (аь ..., а„) и Р(г) = (Ьх, ..., Ь„) длиной п = |Р|, для которых а, = F(p„ t) и bi=F{t, р,) для всех I. Переход t может сработать при некоторой разметке М сети N, если каждое входное место р перехода / имеет разметку не меньшую, чем кратность дуги, соединяющей р и г, т. е М(р) > F(p, t) для всех р &'t. Это условие можно переписать в векторной форме следующим образом: М >'F(f). Для ординарной сети Петри условие срабаты- вания перехода означает, что любое входное место этого перехода содержит хотя бы одну фишку, т. е. имеет ненулевую разметку. Срабатывание перехода t при разметке М порождает разметку М' = М-*F(f) + F*(/), т. е. М'(р) - М(р) - F(p, /) + F(i, р) для всех р е Р. Таким образом, срабатывание пе- рехода t изменяет разметку так, что разметка каждого его входного места р уменьша- ется на кратность дуги, соединяющей р и t, а разметка каждого его выходного места увеличивается на кратность дуги, соединяющей t и р На множестве разметок можно ввести отношение [ > непосредственного следования разметок- М [ > М' тогда и только тогда, когда существует такой переход /е 7, что М >’F(t) и М'= М - 'F(t) +F(Z). Будем использовать уточняющее обозначение M[t> М', если М' непосредственно следует после М в результате срабатывания перехода /. Говорят, что разметка М' достижима от разметки М, если существует последо- вательность разметок М,МХ,М2,..., М' и слово т = t\t2...tk в алфавите Т такие, что Л/[Л > A/|[z2 > М2... [tk > М'. Слово т в этом случае называется последовательностью срабатываний, ведущих от М к М'. Обобщим отношения непосредственного следования до отношения "М' дости- жима от М", используя обозначение Л/[ > Л/'или М[т > М', если уточняется последо- вательность срабатываний. При этом последовательность т может быть пустой, т. е. М достижима от М. Множество { М'-. М[> М'} разметок, достижимых в сети N от разметки М, обозначим через R(N, М). Множество R(N) = 7?(2V, Л/о), т. е. множество всех разметок, достижи- мых в N от начальной разметки Л/о, называют множеством достижимых разметок сети N. (Заметим, что М е R(N, М) и Мо & /?(/V).) Множеством последовательностей срабатываний сети Д' или свободным языком сети N называется множество £(Д) всех последовательностей срабатываний, ведущих от Л/о к каждой достижимой в /V разметке, т. е. £(7V) = {т е Г*: существует такая разметка MeR(N), что Л/0[т > М}.
976 Часть II. Применение графов и граф-моделей Рис. 12.29. Пример сети Петри На рис. 12.29 изображена сеть Петри N, в которой Р = (pi,p2,p3) и Т = {/ь г2, 13, М- Функция инцидентности Fee™ Nзадается с помощью табл. 12 6 и 12.7, в которых на пересечении строки х и столбца^ стоит число F(x, у): Таблица 12.6. Функция инцидентности переходов с местами F(b, Pj) P2 Рз 6 1 1 0 ‘2 0 0 1 h 0 2 0 1 0 0 Таблица 12.7. Функция инцидентности мест с переходами F(Ph t) t. tl fe ti Pi 1 1 0 0 P2 0 2 0 0 Рз 0 0 1 1 Начальная разметка Мо задается следующим образом: М0(р{)=\, Л70(/?2) = 2, М0(р3) ~ 0 или в векторной форме Мо = (1,2,0). При разметке Мо могут сработать переходы Ц и /2, т. к. Мо = (1,2,0) > ’Р(ц) = (1,0,0), Л/о >'F(/2) = (1,2,0). Переходы /3 и /4 не могут сработать, т. к. Мо > 'F(t-C) = (0,0,1), Мо Z’F(tJ = (0,0,1). В результате срабатывания перехода Ц разметка Мо сменяется на разметку (1,3,0), а в результате срабатывания перехода /2 разметка Мо сменяется на разметку (0,0,1). Обе новые разметки непосредственно следуют после Мо в рассматриваемой сети. Разметка М е R(N) называется тупиковой, если в сети W не существует ни одного перехода, который может сработать при этой разметке. Граф разметок сети N— это ориентированный граф, множество вершин которого образовано множеством R(N) достижимых в N разметок, а дуги графа представляют возможные изменения разметок сети N: из вершины М в вершину М' ведет дуга, по- меченная символом перехода / тогда и только тогда, когда M[t > М'.
Гпава 12. Прочие граф-модели 977 Легко видеть, что если выделить путь по дугам графа разметок, начинающийся в вершине М и заканчивающийся в вершине М', и выписать подряд все встречающиеся символы переходов, то полученное слово образует последовательность срабатыва- ний, ведущих от М к М'. Множество всех слов, полученных выписыванием символов переходов вдоль путей, начинающихся в Л/о, образует множество последовательно- стей срабатываний сети или так называемый ее свободный язык. Рис. 12.30. Начальный фрагмент графа разметок сети Петри На рис. 12.30 показан начальный фрагмент графа разметок сети на рис. 12.29. Этот граф бесконечен, т. к. бесконечно множество R(N) достижимых разметок для рас- сматриваемой сети N. Язык сети N тоже является бесконечным и включает пустое слово е, а также слова /[,^2, ^1^2? Т2Т3, Л^2^4> Ifitizh, tihhtu Для рассматриваемой сети TV тупиковыми являются разметки (0,2,0), (0,3,0),.... (0,27,0),.... Следующее свойство характеризует эффект увеличения начальной разметки в сети Петри. А. Для любых сетей Петри N~ (Р, Т, F, W, Мо) и N'= (Р, Т, W, Мо + К), где К — про- извольный целочисленный вектор с неотрицательными элементами, справедливы следующие свойства:
978 Часть II. Применение графов и граф-моделей П L(N) с, L(N У, □ Л/е R(N)=>(M+K) е R(Ny, □ Л/,[т > М2 => (Mi + К) [т > (М2 +К). 12.3.3. Основные свойства сетей Петри Место р в сети Петри N=(P, Т, W, Мо) называется ограниченным, если существует число и такое, что для любой достижимой в сети разметки М справедливо неравенст- во М(р) < п. Сеть W называется ограниченной сетью, если любое ее место ограни- чено. Ясно, что множество достижимых разметок R(N) конечно, если и только если N— ограниченная сеть. В сети на рис. 12.29 места рх и р3 ограничены, т. к. каждое из них может содержать не более одной фишки. В то же время место р2 не ограничено, и поэтому эта сеть не является ограниченной. Место р называется безопасным, если М(р) < 1 для любой разметки М е R(N); соответственно, сеть безопасна, если все ее места безопасны. Любая достижимая в безопасной сети разметка представляет собой вектор из 0 и 1. Ограниченность и безопасность характеризуют емкость условий: в дискретной ин- формационной системе, моделируемой соответствующими сетями, можно огра- ничить емкость накопителей, необходимых для хранения условий наступления собы- тий. Родственным этим понятиям является понятие консервативной сети, в кото- рой сумма фишек во всех ее местах остается постоянной при работе сети, т. е. е г Л/|(р) = е ;> М2(р) для любых разметок Mi, М2 е R(N). В консервативной сети каждый переход консервативен в том смысле, что его срабатывание не меняет число фишек в сети, т. е. |71 = |. Переход в сети может сработать при определенных условиях, связанных с разметкой его входных мест. В общем случае может оказаться, что для некоторого перехода условие его срабатывания никогда не выполняется, как бы ни функционировала сеть. Такой переход— лишний в сети, его можно исключить без ущерба для работы сети. Может случиться также, что после некоторой последовательности срабатываний пе- реходов сети и соответствующих изменений ее разметки некоторые переходы, в том числе те, которые уже срабатывали, больше никогда не сработают, какие бы вариан- ты достижимых в сети разметок не возникали. Это означает, что в моделируемых системах могут появляться ситуации, тупиковые для некоторых событий, "исклю- чающие их из дальнейшей игры". Например, в операционных системах подобные случаи имеют место при взаимных блокировках процессов (deadlocks). Следующие определения связаны с выявлением таких ситуаций в сетях Петри. Переход t в сети Петри N-(P, Т, F, W,M0~) называется потенциально живым при разметке М е R(N), если существует разметка М', достижимая от М, т. е. Л/'g R(N,M), при которой переход t может сработать, т. е. для которой М'> *F(t). Если М= Mq, то / называется потенциально живым в N.
Гпава 12. Прочие граф-модели 979 Переход t е Т называется живым, если t является потенциально живым при любой М е R(N). Сеть называется живой, если все ее переходы живы. Переход t е Т — мертвый при разметке М, если он не является потенциально живым при М. Переход t — мертвый, если он мертв при любой М е R(N). Переход t — потенциально мертвый, если существует такая разметка М s R(N), что при любой разметке М' е R(N, М) переход t не может сработать; разметка М в этом случае называется t-тупиковой. Если разметка Мявляется /-тупиковой для всех t е Т, т. е. R(N, М) = {Л/}, то М — ту- пиковая разметка. Переход t называется устойчивым в сети N, если для любого перехода t'e Т, отлич- ного от t, и любой разметки М е R{N), если М> ’F(f) и М> ’F(f), то М> *F(t) + ’F(t')), т. е. если переход t может сработать, то никакой другой переход не может, сработав, лишить его этой возможности. Сеть Nустойчива, если все ее переходы устойчивы. 12.3.4. Ограниченность и безопасность сети Некоторое место р в сети N может оказаться неограниченным по двум причинам. Первая (неограниченность "первого рода") заключается в следующем. Пусть свобод- ный язык сети £(7V) содержит такую последовательность срабатываний т = Т|Т2, что Л/о[Т| > Л/|[т2 > М2, Л/2 > Л/, и М2(р) > М\(р)- Поскольку М2 > М\, то любая последова- тельность срабатываний, начинающаяся при разметке Л/ь может повториться и начи- ная с разметки М2, т. е. Т|Т2" е ЦП) для любого п. Следовательно, разметка места р может безгранично расти. Однако не все неограниченные места сети удовлетворяют описанным условиям. Есть места р, которые не обладают неограниченностью "первого рода", но могут получать сколь угодно большое, но конечное число фишек при многократных срабатываниях переходов, входные места которых являются неограниченными. Таким образом, не- ограниченность таких мест р "вторична" по отношению к неограниченности других мест. Исследование проблемы ограниченности сети Петри сводится к анализу графа, полу- чившего название покрывающего дерева сети. Для любой сети такой граф конечен и может быть построен с помощью следующего алгоритма. Алгоритм 12.2. Покрывающее дерево сети Петри Дано. Сеть Петри N = (Р, Т, F, W, Мо). Требуется. Покрывающее дерево D сети N. Метод. Первоначально предполагается, что дерево D тривиально и состоит из един- ственной вершины Л/о, которая не объявлена листом. Затем для каждого листа М де- рева D, который еще не объявлен листом, выполняется одно из следующих действий в зависимости от возможного случая: □ если ни один из переходов сети N не может сработать при разметке М, т. е. М '£' F(t) для любого t е 7, то вершина М объявляется листом;
980 Часть II. Применение графов и граф-моделей □ если на пути из корня дерева D в вершину М лежит вершина Л/'такая, что М = М', то вершина М объявляется листом; □ если на пути из корня дерева D в вершину М лежит вершина Л/'такая, что М'< М, то для любого места р, для которого М'(р) < М(р), заменяется на со значение соот- ветствующей месту р координаты М и вершина Л/объявляется со-листом; □ если ни один из перечисленных случаев не имеет места, то М— внутренняя вер- шина дерева D и для каждого перехода t е Т такого, что М > ’F(t), в дерево добав- ляется новая вершина М'= М-*F(t) + F" (/), а также дуга, ведущая из М в М', по- меченная символом t. Из правил построения покрывающего дерева для сети Петри следует, что вершины дерева представляют собой векторы из множества 7V"fo, где п— число мест сети, а N(O=N'U {со} расширенное множество натуральных чисел. Предполагается, что со — элемент, удовлетворяющий для любого и е N следующим свойствам: □ со > и; □ п + со = со + и ~ со + со = со- и = со- со = со; □ со л = л • со = со; □ 0 со = со • 0 = 0. Алгоритм распознавания ограниченности сети Петри 7V состоит в построении покры- вающего дерева сети и последующем просмотре конечного числа его вершин- разметок. Если будет найдена хотя бы одна разметка с символом со, то сеть N не огра- ничена, в противном случае она ограничена. Рассмотренный алгоритм выявляет лишь тот глобальный факт, является ли заданная сеть N ограниченной или нет. Он основывается на том свойстве, что в покрывающем дереве со появляется только в тех позициях разметок-векторов, которые соответству- ют местам с потенциально неограниченной разметкой первого рода. Алгоритмом нельзя установить, какие места сети N могут иметь неограниченную разметку второго рода. Чтобы иметь такую возможность, можно использовать полное покрывающее дерево, которое может быть построено по следующему алгоритму. Алгоритм 12.3. Полное покрывающее дерево Дано. Сеть Петри N = (Р, Т, F, W, Мо). Требуется. Полное покрывающее дерево D для N. Метод. Строится покрывающее дерево D сети N. Если это дерево не имеет со- листов, то построение полного покрывающего дерева закончено, и оно совпадает с D. Если покрывающее дерево D содержит необработанный со-лист М, то для него стро- ится покрывающее дерево для сети N', полученной из 2V заменой начальной разметки Мо на разметку М. При этом правила срабатывания переходов и изменения разметки сети обобщаются на случай векторов из Л/' с учетом арифметических свойств расши- ренного множества натуральных чисел Аю. Построенное дерево присоединяется к основному дереву совмещением корня М в новом дереве с листом М в основном де-
Глава 12. Прочие граф-модели 981 реве. Процесс обработки D повторяется до тех пор, пока не исчезнет в нем последний необработанный со-лист. Пусть D— полное покрывающее дерево сети Петри N. Справедливы следующие свойства: A. D — конечное дерево. Б. Некоторое место р сети N не ограничено тогда и только тогда, когда среди вершин дерева D существует такая вершина М, что в позиции места р стоит сим- вол СО. В. Сеть Н безопасна тогда и только тогда, когда все вершины дерева D представ- ляют собой векторы из множества {0, 1}". Г. Переход t сети N потенциально живой тогда и только тогда, когда он метит некоторую дугу в D хотя бы один раз. Д. Некоторое место р сети N может получить фишку в процессе функционирова- ния сети тогда и только тогда, когда хотя бы в одной вершине D позиция, соот- ветствующая месту р, содержит число п> 0. Полное покрывающее дерево сети является удобным инструментом ее анализа. На- пример, чтобы узнать, может ли данный переход t сети N сработать сколь угодно большое число раз, достаточно присоединить к данному переходу новое "висячее" выходное место р и затем выяснить, является ли оно неограниченным. Чтобы для произвольного вектора М е Г/',Л и для произвольного перехода / в сети Петри N с п местами узнать, является ли /-тупиковым вектор М, можно заменить в сети N началь- ную разметку Мо на разметку М, после чего построить полное покрывающее дерево для полученной сети с начальной разметкой М, являющейся корнем этого дерева; ясно, что М— /-тупиковый вектор тогда и только тогда, когда так построенное пол- ное покрывающее дерево не содержит дуги, помеченной символом /. 12.3.5. Классы языков сетей Петри Проблемы, рассмотренные в предыдущих разделах, связаны, главным образом, с разметкой сети и соответствуют таким прикладным задачам, которые требуют ана- лиза возможных ситуаций (состояний) в моделируемых сетями системах, анализа характера изменений в них. Другой важный круг проблем связан с динамикой функционирования системы, кото- рая характеризуется множеством возможных последовательностей реализации в ней событий. Поскольку события системы представлены переходами сети, ее функциони- рование можно описать в терминах последовательностей срабатываний переходов В сети все символы-переходы различны. Однако в системах, моделируемых сетями часто удобно считать разные события одинаковыми, тождественными в некотором смысле. Для учета таких возможностей вводятся специальные пометки, отмечающие "одинаковые" и "разные" переходы. Эти пометки представляют собой символы из некоторого алфавита S, в общем случае отличного от алфавита Т, а сами сети назы- вают помеченными. В зависимости от правил пометки переходов и правил формиро-
982 Часть II. Применение графов и граф-моделей вания последовательностей срабатываний выделяются различные классы языков, по- рождаемых сетями Петри. Помеченная сеть Петри — это пара (N, G), где N— сеть Петри, a G : Т —> S — поме- чающая функция. Если G— частичная функция, т. е. некоторым переходам t не со- поставляется никакого символа из Е, то эти переходы называются е-переходами и трактуются как переходы, помеченные символом пустой строки е, т. е. G(z) = е. Помечающая функция М расширяется на последовательности срабатываний естест- венным образом: G(e) = е и F(M) = G(t)G(z) для любой цепочки т е 7* и любого пере- хода t & Т. Для последовательности срабатываний т е 1* сети Петри N и помеченной сети (N, G) слово G(a) е Е* называют помечающей последовательностью. Помеченные сети с е-переходами удобны в тех случаях, когда при моделировании системы нужно ввести вспомогательные переходы, не связанные непосредственно с событиями системы. С их помощью можно также "маскировать" те события, которые не должны рассматриваться в данной задаче моделирования. Префиксный язык помеченной сети (N, G) — это множество {G(t) : т 6 ЦП)}. Во многих приложениях бывает удобно или необходимо рассматривать не свободный язык сети Петри N, включающий все ее последовательности срабатываний, а некото- рое подмножество терминальных последовательностей L(N, Mj), которое определяет- ся некоторой фиксированной терминальной разметкой Mf и состоит из всех последо- вательностей, ведущих от начальной разметки Мо к разметке Mt, т. е. L(N, Mj) = = {т е 7*: Мо [т > М/-}. Множество L(N, Mj) образует свободный терминальный язык сети N (относительно терминальной разметки Mj). Соответственно, множество {G(t) : т е L(N, Mj)} образует терминальный язык помеченной сети (N,G) (относи- тельно терминальной разметки Mj). Для сети N на рис. 12.31 свободный язык представляет собой множество Z(7V) = {Z|"1/2"2f3”’Z4”4 : И] > 0, 1 > и2 > О, щ-п2> п3>0, п2> п4>0}, а свободный терми- нальный язык L(N, Mj), где Mf = (0, 0, 0, 1), представляет собой множество L(N, Mj) = = 0}. Поскольку для помеченной сети M=(7V, G0 на рис. 12.32 поме- чающая функция взаимно-однозначно сопоставляет переходам сети символы из Е = {a, b,c,d}, то ее префиксный язык и терминальные языки получаются из соответ- ствующих языков непомеченной сети 7V (см. рис. 12.31) прямой заменой символов- переходов геГ на соответствующие символы из Е. Для помеченных сетей N2 =(N, G2) и M=(7V, G3), изображенных на рис. 12.33 и 12.34, их префиксные и терминальные для Mf= (0,0,0,1) языки образуют множества: L(N, G2) = {a"bm : п > т >0}, L(N, G2, Mj) = {d'bn : n > 0}, L(N, G3) = {d\bn2c"3 : 1 > n, > 0, щ = 0 -> n2 = 0, n, = 1 -> —> л2 > 0, «! > w3 > 0}, L(N, G3, Mj) = {ab"c : n > 0}. Пусть N — класс всех сетей Петри. На основе введенных определений языков разного типа для сетей Петри и помеченных сетей Петри можно образовать разные классы языков, из которых обычно выделяются следующие: □ Г — класс префиксных языков сетей Петри, который образован из префикс- ных языков всех помеченных сетей, получаемых из сетей класса N с помощью
Глава 12. Прочие граф-модели 983 Рис. 12.33. Помеченная сеть (Л/, Gz)
984 Часть II. Применение графов и граф-моделей Рис. 12.34. Помеченная сеть (N Gz) произвольных (в том числе частичных) помечающих функций над произвольными алфавитами; □ — класс терминальных языков сетей Петри, который образован из терминаль- ных языков всех помеченных сетей, получаемых из сетей из N, в том числе поме- ченных сетей с е-переходами; □ Ln Lo— подклассы классов Д’ и 1^ соответственно, которые включают префикс- ные и терминальные языки всех помеченных сетей, не содержащих е-переходов; □ И и классы свободных префиксных языков и свободных терминальных язы- ков всех сетей из N. Поскольку можно рассматривать помеченные сети, в которых помечающая функция G сопоставляет любому t е Т элемент G(t) = t е Т, то можно считать классы l! и подклассами классов L и Д соответственно. Для сопоставления друг с другом введенных классов полезной оказывается специаль- ная стандартная форма помеченных сетей. Сеть, преобразованная в стандартную форму, сохраняет префиксный и терминальный языки, хотя в стандартной форме и появляются новые переходы и места. Помеченная сеть (N, G) находится в стандартной форме, если: □ в сети выделено специальное "включающее" место р таким образом, что М0(р) = 1 и Л/о(<7) = 0 для всех мест q, отличных от р\ □ терминальный язык сети определяется для одной и той же терминальной разметки Л/у= 0 = (0, 0,..., 0), при которой Mj(q) = 0 для всех мест сети; □ каждый переход сети имеет хотя бы одно входное место, т. е. разметка 0 является для нее тупиковой. А. Для любой помеченной сети (N, G) и любой терминальной разметки Mt существу- ет представленная в стандартной форме такая помеченная сеть (N', С), что L(N', О') = £(А, G) и L(N', G', 0) = L(N, G, МД
Глава 12. Прочие граф-модели 985 Б. Любой язык из классов L, IX Lq, Д, может быть порожден некоторой помеченной сетью в стандартной форме как ее терминальный язык для терминальной разметки Mj= 0. Соотношения между классами языков сетей Петри можно изобразить следующей схемой, в которой стрелки указывают отношение включения: l! -> L -> Г 4. 4, 4^ z<i —> Lq —> 4ц Таким образом, оказывается, что классы терминальных языков более мошны, чем классы префиксных языков, помеченные сети Петри оказываются более мощным мо- делирующим инструментом, чем непомеченные, а е-переходы еще больше усиливают моделирующие способности сетей. В. Класс помеченных сетей Петри строго мощнее класса конечных автоматов, не сравним с классом магазинных автоматов и строго менее мощен, чем класс машин Тьюринга. 12.3.6. Подклассы сетей Петри Сети Петри моделируют широкий спектр дискретных систем, но для некоторых рас- пространенных специальных классов систем удобно применять сети Петри не общего вида, а некоторые их подклассы, более простые и более адекватные рассматриваемым системам. Не все вопросы анализа сетей Петри общего вида разрешимы. Так, не раз- решимы задачи эквивалентности и включения для множеств достижимых разметок- сетей Петри и языков сетей Петри, хотя эти задачи могут оказаться очень важными для получения оптимальных сетей Петри. Даже те вопросы анализа сетей, которые разрешимы, очень трудны в смысле требования большого объема вычисления. Поэтому вводились и изучались различные подклассы сетей Петри, получаемые в ос- новном путем упрощения топологии (графовой структуры) сетей. Напомним, что в общем случае кратность дуги в сети Петри может быть любым не- отрицательным числом, но если все дуги имеют одну и ту же кратность, равную 1, то сеть относится к подклассу ординарных сетей. Подкласс ординарных сетей не являет- ся существенным сужением класса сетей Петри, и по отношению к большинству сво- их сетей оба класса оказываются эквивалентными в том смысле, что для сети Петри с заданным набором свойств можно построить с помощью преобразования Хака орди- нарную сеть, обладающую тем же набором свойств. Преобразование Хака произвольной сети Петри N=(P, Т, F, W, Мо) в ординарную сеть 7V'= (Р' Т\ F\ W', Мо) состоит в следующем: □ для каждого места р е Р по формуле max (F(p, t) + F(t, р)) определяется макси- <е’Г мальная кратность п(р) дуг, инцидентных этому месту;
986 Часть II. Применение графов и граф-моделей □ каждому месту р е Р в сети N' соответствует множество Р'(р), состоящее из и(р) местрьр2, □ каждому переходу t е Т в сети /V' соответствует единственный переход, обозна- чаемый тем же символом t, а также множество Т'(р) = {гь г2,ги(р)} новых пере- ходов, которые связывают места из Р'(р) в кольцевую сеть, как показано на рис. 12.36. При этом если п(р) = 1, то новые переходы не вводятся; □ для каждой дуги сети N, связывающей место р с некоторым переходом t и имею- щей кратность lV(p, t), заводятся W (р, t) дуг, связывающих t с местами Р\,р2, —,рП{р). При этом распределение дуг в сети ЛГ'по местам р\,р2, —,Рщр) про- извольно, лишь бы не возникали ситуации, когда переход и место связаны более одной дугой. На рис. 12.37 показано возможное распределение дуг в ординарной сети, построенной по сети рис. 12.35; □ начальная разметка места р, е Р '(р) в сети N' определяется следующим об- разом: МЗфх) = М0(р) и Мо(р^ = 0 для всех i > 1. Рис. 12.36. Преобразование Хака; заведение новых переходов
Глава 12. Прочие граф-модели 987 Рис. 12.37. Преобразование Хака; результирующая ординарная сеть А. Преобразование Хака сохраняет основные свойства исходных сетей — живость, ограниченность, консервативность. Б. Ординарные сети Петри генерируют те же классы языков L, Lq, IP, 1^, что и се- ти Петри с кратными дугами. В. Класс свободных языков сетей Петри строго включает класс свободных языков ординарных сетей Петри. Два наиболее простых подкласса сетей Петри образуются за счет наложения более строгих топологических ограничений на структуру сети N = (Р, Т, F, W, Мо). Сеть Петри N называется автоматной сетью, если каждый переход t е Т сети N име- ет ровно одно входное и ровно одно выходное место, т. е. |*Г| = |/"| = 1. Сеть Петри 7V называется синхронизационным графом (или синхрографом, или мар- кированным графом), если в каждое место сети входит ровно одна дуга и из каждого места исходит ровно одна дуга, т. е. |*р| = |р’| = 1 для любого р е Р. Оба рассмотренных подкласса являются подклассами ординарных сетей Петри. Любая автоматическая сеть консервативна и ограничена. Поэтому ее граф разметок конечен, и, следовательно, в классе автоматных сетей разрешимы проблемы дости- жимости разметки, живости, включения и равенства множеств достижимых разметок, эквивалентности языков сетей и все другие проблемы анализа свойств сетей. Все это следствие того, что автоматные сети представляют собой, по существу, сетевую фор- му задания конечных автоматов. Граф разметок автоматной сети — это не что иное, как граф конечного автомата, в котором множество состояний образовано множест- вом достижимых в сети разметок, а алфавит — символами переходов сети. Г. Автоматная сеть безопасна тогда и только тогда, когда ее начальная разметка содержит ровно одну фишку.
988 Часть II. Применение графов и граф-моделей Д. Автоматная сеть жива тогда и только тогда, когда она представляет собой сильно связный граф и ее начальная разметка содержит хотя бы одну фишку. В отличие от автоматных сетей, синхрографы могут описывать параллелизм событий, но не допускают изображения конфликтных ситуаций. Основные свойства, в том чис- ле живость и достижимость разметки, распознаваемы в классе синхрографов, причем на основе простого анализа структуры графа и его начальной разметки. Е. Синхрограф N является живым тогда и только тогда, когда любой цикл в нем при начальной разметке Мо не пуст, т. е. содержит хотя бы одну фишку. Ж. Живой синхрограф N является ограниченным тогда и только тогда, когда каж- дое его место входит в некоторый цикл. 3. Живой синхрограф N безопасен тогда и только тогда, когда каждое его место входит в некоторый Цикл, содержащий ровно одну фишку при начальной размет- ке Mq. Свободная сеть (или сеть со свободным выбором) — это такая сеть Петри, в которой дйя любой дуги и, ведущей из места к переходу, справедливо хотя бы одно из сле- дующих свойств: и начинается местом, из которого не исходит ни одной другой дуги; и заканчивается переходом, в который не ведет никакая другая дуга. Класс свободных сетей, как видно из его определения, является подклассом однород- ных сетей Петри и строго включает классы автоматных сетей и синхрографов. Пусть задана сеть Петри N = (P, Т, F, IV0). Ловушкой сети N называется такое не- пустое подмножество мест Q cz Р, что Q’ с 'Q, где Q'={q’: q е Q} и 'Q={‘q : q е Q}. Тупиком сети N называется такое непустое подмножество мест /? с Р, что 'R <г /?". Справедлив следующий критерий Коммонера — Хака живости свободной сети. И. Свободная сеть жива тогда и только тогда, когда каждый ее тупик содержит размеченную (т. е. содержащую хотя бы одну фишку) ловушку. В сети Петри N— (Р, Т, F, Мо) замкнутой подсетью, задаваемой подмножеством мест Q с Р, называется сеть (Q, Т' F', Мо), в которой Т'= 'Q r\ Q', F'=Fr> (Q х Г'иГх Q), Мо — проекция Мо на места из Q. Говорят, что сеть Л'' покрыта заданной совокупностью замкнутых подсетей, если каждое место сети входит в одну из подсетей этой совокупности. К. Свободная сеть безопасна тогда и только тогда, когда она может быть покры- та совокупностью сильно связных автоматных замкнутых подсетей. 12.3.7. Обобщения сетей Петри Анализ языков, порождаемых сетями Петри, показывает, что сети Петри по вырази- тельной мощности, т. е. по способности моделировать поведение дискретных систем, превосходят такие классы моделей, как конечные автоматы, но все же не обладают "универсальными" возможностями, т. к. некоторые классы языков не могут порож- даться сетями Петри.
Глава 12. Прочие граф-модели 989 Рассматриваемые обобщения сетей Петри приводят к универсальным моделирующим системам, порождающим класс рекурсивно-перечислимых языков, т, е. к системам, равномощным машинам Тьюринга. Этот факт проще устанавливается сравнением обобщенных сетей со счетчиковыми автоматами, модификациями машин Минского, которые, как известно, равномощны машинам Тьюринга. Сравнение счетчиковых автоматов с сетями Петри показывает, что пяти из шести типов операторов автомата можно сопоставить фрагменты сетей Петри, имитирую- щие их работу. Однако оператор условного вычитания если х,*0 то х,:=х,— 1 не удается промоделировать средствами сетей Петри. Причина этого состоит в том, что в сети Петри можно заметить (и отметить это срабатыванием перехода) тот факт, что место сети изменило разметку с нулевой на ненулевую, но нельзя отметить срабаты- ванием перехода факт изменения разметки с ненулевой на нулевую. Ингибиторная сеть представляет собой сеть Петри, дополненную специальной функцией инцидентности Л): Р х Г—> {0,1}, которая вводит ингибиторные дуги для тех nap (р, I), для которых Ft(p, t) = 1. Правило срабатывания переходов в ингибитор- ной сети модифицируется следующим образом. Переход / может сработать при раз- метке М, если М(р) > F(p, f) и M(p)-Ft(p, г) = 0 для всех р е г Рис. 12.38. Пример ингибиторной сети Петри На рис. 12.38 изображен фрагмент ингибиторной сети, моделирующий оператор ус- ловного вычитания; здесь (как и обычно) ингибиторные дуги изображены кривыми, которые заканчиваются не стрелками, а маленькими кружочками А. Любой рекурсивно перечислимый язык может быть порожден помеченной инги- биторной сетью как префиксный или терминальный язык сети. Рассмотрим следующую модификацию определения сети Петри. Вводится множество приоритетов PR, элементы которого частично упорядочены некоторым отношением < (больше или равно) и сопоставлены переходам t е Т некоторой функцией pr(f) g PR. Правило срабатывания перехода модифицируется путем дополнения его следующим условием: переход t может сработать, если для любого другого перехода t', который может сработать по стандартному условию, pr(t') < рг (t). Другими слова- ми, если несколько переходов готовы сработать, то срабатывает любой такой пере- ход, приоритет которого не меньше приоритетов остальных готовых к срабатыванию переходов. Такую модификацию сети Петри называют сетью с приоритетами.
990 Часть II. Применение графов и граф-моделей 2 рг(г)=2 Рис. 12.39. Пример сети Петри с приоритетами На рис. 12.39 показан пример простой сети с приоритетами, для которой в качестве множества приоритетов выбрано множество натуральных чисел и отношение между приоритетами совпадает с отношением "больше или равно" на числах. Она модели- рует оператор условного вычитания единицы счетчикового автомата. Б. Любой рекурсивно перечислимый язык может быть порожден помеченной сетью с приоритетами как ее префиксный или терминальный язык. В. Проблемы ограниченности, достижимости, эквивалентности по префиксным и терминальным языкам, пустоты этих языков неразрешимы для ингибиторных сетей и сетей с приоритетами. Разные модификации сетей Петри предлагались в первую очередь для того, чтобы более адекватно и удобно выражать в терминах сетей особенности функционирова- ния реальных дискретных систем. Эти модификации приводят к классам сетей, стро- го более мощным, чем класс сетей Петри. Например, при моделировании сетями Петри дискретных систем фишки часто соот- ветствуют различным объектам, передаваемым между компонентами системы: дан- ным в информационных системах, деталям, ресурсам и т. п. Зачастую эти объекты имеют дополнительные атрибуты, позволяющие различать их и использовать эти раз- личия для управления функционированием системы. Для адекватного описания подобных ситуаций можно использовать раскрашенные сети— модификацию сетей Петри, в которой фишкам приписаны некоторые при- знаки, например различные цвета, а условия срабатываний переходов и правила из- менения разметки сети задаются специальной таблицей, учитывающей цвета фишек. На рис. 12.40 и 12.41 показан пример такой раскрашенной сети. Сеть моделирует фрагмент операционной системы, управляющий обменами между тремя накопителя- ми на магнитных дисках D\, D2, D3 и центральным процессором через два канала А и В. В этой сети использованы следующие фишки с признаками: □ ф, d2, ф — фишки, отмечающие возможность связи с дисководами D\, D2, D3; П а, Ь — фишки, отмечающие доступность каналов А и й; □ а, р, у, 8, е — вспомогательные фишки для запоминания предыстории функцио- нирования системы.
Гпава 12. Прочие граф-модели 991 Рис. 12.40. Пример раскрашенной сети Петри Pl Pl Ре Р2 Pi Pi Pl /] ct /2 а Ф Ф 6 Ф a p а Ф Ф Ф a Y а Ф Ф Ф b 6, Ф b E Рз Ра Ра PS Pb Р7 Ps *4 Р Р Р а Ф a a Y Y Y а Ф a б, б, б, а Ф b Е £ Е а Ф b Рис. 12.41. Табличное задание раскрашенной сети Выразительная мощность раскрашенных сетей зависит от мощности множества при- знаков. Класс сетей с конечным множеством признаков эквивалентен классу сетей Петри, хотя при преобразовании раскрашенной сети в эквивалентную сеть Петри мо- гут значительно возрасти размеры сети. Сети с бесконечным множеством признаков могут моделировать счетчиковые автоматы, и, следовательно, класс таких сетей рав- номощен классам ингибиторных сетей. Еще одна модификация связана с изменением правила функционирования сетей — синхронные сети. В этой модификации работа сети разбивается на такты. В начале каждого такта выясняется (по стандартным условиям срабатываний), какие переходы
992 Часть II. Применение графов и граф-моделей могут сработать. Далее из них выбирается некоторое максимальное множество Т' взаимно неконфликтующих переходов, т. е. таких, что Z, е г F(p, t) < М(р) для всех р е Р. Затем все такие переходы срабатывают в любом порядке, изменяя разметку обычным образом На этом заканчивается текущий такт, после чего начинается но- вый такт при новой разметке. Такое изменение правил функционирования сетей приводит к увеличению их вырази- тельной мощности до уровня машин Тьюринга. В сетях с приоритетами и в синхрон- ных сетях происходит отход от чисто, локального принципа управления функциони- рованием сети, принятого в сетях Петри. Именно в силу привлечения данных о гло- бальной ситуации в системе и возрастает выразительная мощность сетей. Аналогичный подход просматривается в самомодифицируемых сетях Фалька. В се- тях этого класса каждой дуге (р, /) и (/, р) приписана модифицируемая кратность V(p, f) или Е(/, р) Если кратность дуги — число, то оно имеет тот же смысл, что и кратность в определении сетей Петри. Но в качестве кратности может выступать символ q некоторого места данной сети. В этом случае кратность дуги переменна и равна текущей разметке M(q) места q. Правило срабатывания перехода t в самомоделируемых сетях изменяется следующим образом: для любого р е 7 должно выполняться М(р) > V(p, t), где V(p, t) = п, если дуга (р, /) помечена числом п > 1, и Е(р, /) = M(q), если дуга (р, /) помечена символом места q. Правило изменения разметки сети после срабатывания перехода t выглядит так. Лю- бое место р g Р получает М(р) - Ff/p, t) + F^t, р) фишек, где FM— модифицируемая функция инцидентности, которая определяется по следующим правилам: п, О, если xFy ил — число Е(х,у), если xFy и q — символ места V(x,y), если нет дуги (х,у), т. е. -> (xFy). Введение модифицируемой кратности позволяет достаточно просто моделировать ингибиторные сети и сети с приоритетами Поэтому модифицируемые сети порож- дают класс рекурсивно перечислимых языков и основные сетевые проблемы для них неразрешимы. 12.3.8. Регулярные сети Сеть Петри определялась как набор из множеств мест и переходов, отношения инци- дентности и функции начальной разметки. Такой способ задания обычен для поста- новки и решения теоретических задач анализа сетей. Диаграммное представление сетей в виде изображения двудольного графа удобно применять в иллюстрированных целях. Однако оба эти способа представления не вполне подходят для прикладных задач моделирования дискретных систем, например, для многих из задач, включаю- щих автоматический анализ, синтез и преобразование сетевых моделей с помощью ЭВМ. В ряде таких задач более удобным оказывается или матричное, или аналитиче- ское представление сетей.
Глава 12. Прочие граф-модели 993 В первом случае сеть Петри задается целочисленными матрицами, кодирующими представление сети Петри в виде помеченного графа. Аналитическое представление сети задает ее с помощью формулы в некоторой алгебре сетей. Эта формула построе- на из символов, задающих некоторые элементарные сети, и сетевых операций, с по- мощью которых описываемая сеть может быть построена из элементарных сетей. Класс регулярных сетей, для которых такое представление возможно, формально яв- ляется подклассом сетей Петри за счет топологических ограничений. Однако этот класс эквивалентен по порождаемым языкам классу (ординарных) сетей Петри. Алгебра регулярных сетей строится с помощью операций над множеством элемен- тарных сетей, каждая из которых имеет вид автоматной сети, состоящей из одного перехода а и двух мест: головного а , являющегося входным для а, и хвостового а, являющегося выходным для а. В формальном представлении элементарная сеть обо- значается символом ее единственного перехода а. В классе регулярных сетей обобщено понятие разметки. Множество всех целых неот- рицательных чисел расширено за счет введения элемента w, который используется как разметка мест сети и обозначает "неограниченное число фишек" в данном'месте. Заметим, что такое обобщение является формальным, т. к. место с разметкой и> мож- но удалить из сети со всеми инцидентными дугами. Введение мест с "бесконечной разметкой" позволит топологически структурировать сети Петри, не сужая, по суще- ству, класс рассматриваемых сетей. При описании операций над сетями h(N) обозна- чает множество головных мест некоторой сети N, a /(7V) множество ее хвостовых мест. Через TV) As обозначаются исходные сети (Ръ 7\, F, MOi) и (Р2, Т2, F2, М2), а че- рез N— результирующая сеть (Р, Т, F, Мо). Операция наложения N = (Nb N2). Эта операция— обычное теоретико-множест- венное объединение графов, дополненное правилом формирования разметки; с по- мощью этой операции одна сеть накладывается на другую: N=(P = P^<j Р2, T=Tt<j Т2, F^F]VjF2, Л/о), где М0,(р), если pzPj, где / = 1,2, и piPic\P-2, ппп(Л/01(р),Л702(р)), если р&Рхс:Р2. Операция разметки: N=n(N\). Эта операция имеет два параметра: сеть и целое неотрицательное число (или символ <л "бесконечного числа") фишек п. Сеть N = л(М) совпадает как граф с сетью но имеет другую начальную разметку Мо, а именно: п + Мо j (р), есл и р g h(Nt), М0^р)—в противном случае. Остальные операции над сетями определяются с помощью операции наложения и вспомогательной операции слияния мест в сети. Места, возникающие в результате слияния, представляют собой не отдельные символы, а множества символов, что тре- бует некоторого простого обобщения определения сети Петри, в котором место иден- тифицируется множеством символов (в том числе состоящим из единственного сим- вола). Л/0(р) = Л70(р) = 32 Зак. 202
994 Часть II. Применение графов и граф-моделей Операция слияния мест состоит, в свою очередь, из двух подопераций: формирова- ния слитых мест и замены сливаемых мест слитыми. Пусть X = (хь..., х„) и У - (Ун ,Ут)— два сливаемых множества мест сети Л^. Если X или Y— пустое множество, то результат слияния — исходная сеть N\. Операция слияния ц множества мест Л и )'в сети строит новую сеть W= ц(Уь X, У) в два этапа Сначала каждое , г 1 ГН . , место х, е А копируется в т экземплярах х,, ..., х, где т — число мест Y, а в каждое место j; е Y — в п экземплярах у],..., у", где п — число мест в X. Затем каждая пара мест (х^, _>/) заменяется новым местом z = х, иу с разметкой Мфс) = М0}(х,) + Мм(у,) и соответствующими инцидентными им дугами. Операция итерации N = Эта операция унарная, она сливает множество голов- ных мест /г(Л'|) и множество хвостовых мест /(7V,) сети и применима к ней, если эти множества не пересекаются: ‘(ТУ,) = ц(Аь Л(М), /(^)), где h(N})Пl(Nr) = 0. Операция присоединения N = (Nb N2) = N2), h(N2)). По определению го- ловными местами сети 7V являются все головные места сети /У, и те места, в образова- нии которых участвовали места из Л(М); аналогично назначаются хвостовые места сети N. Операция исключения N = (7У| || У2)- Эта операция строит N, сливая головные и хво- стовые места сетей Л'’, и N2. По определению головные места сети N образованы мес- тами, в которые вошли при слиянии головные места сетей и N2, аналогично назна- чаются хвостовые места сети N. Пусть £— класс элементарных сетей, т. е. класс символов-переходов. Формула сети в алгебре, порождаемой классом £ и введенными операциями, определяется по сле- дующим правилам: □ символ из £ — формула; □ если А — формула, то и(Л) и *(Л) — также формулы; □ если А и В — формулы, то (А, В), (А; В) и (А || В) — также формулы. Формулы в предлагаемой алгебре задают класс сетей Петри, которые называются регулярными. Одна и та же регулярная сеть может быть задана различными формулами, которые мы в этом случае считаем тождественными. А. Для произвольных формул А, В, С справедливы следующие свойства коммутатив- ности и ассоциативности операций: (А, В) = (В, А), (А || В) = (В || А), ((А, В), С) = = (Л, (В, О), ((Л; В); С) = (Л; (В; Q), ((А || В) || С) = (Л || (В || Q). При описании свойства используются следующие способы сокращения числа скобок в формулах. С учетом ассоциативности операций формулы вида ((Л, В), Q или (Л, (В, С)) записываются как (Л, В, С). Кроме того, будем опускать самые внешние скобки и введем следующее старшинство операций: унарные по отношениям к сетям операции связывают аргументы сильнее, чем бинарные, а операции и ”||" старше, чем
Гпава 12. Прочие граф-модели 995 Б. Для любых сетей А, В, С и целых чисел n, nt и «2 и справедливы равенства. □ (А, В); С = (А; С), (В; С); □ А; (В, С) = (А; В), (А; С); □ (А, В) ||С = (А || О, (В || О; П *(А, В) = *А, *В, *(А; В), *(В; А); □ *(А || S) = *А || *В = *А || В = А || *В = (*Л; *S); □ (A,A) = A\ □ П\(п2А) = п2(п\А) = («1 + и2)Л; □ п(*А) = *(иЛ); □ п(А, В) = (nA, пВ); □ п(А, В) = (пА~, В)-, □ п(А || В) = (ntA || п2В), где п = щ + п2. Формула А из класса всех формул регулярных сетей называется расслоенной форму- лой, если она имеет вид (Ah А2, ..., А„), где п = 2. А называется стандартно расслоен- ной формулой, если она имеет вид (Ah А2, ..., А„), где п = 2 и А,— формулы, не со- держащие операции наложения. В. Класс формул регулярных сетей и его подклассы — класс расслоенных и класс стандартно расслоенных формул — тождественны в том смысле, что для любой формулы существуют тождественные ей расслоенная и стандартно расслоенная формулы. Г. Класс сетей Петри равномощен его подклассу регулярных сетей, т. е. любую сеть Петри можно преобразовать в эквивалентную ей регулярную сеть. Д. Сеть N= N2,..., Nn) ограничена, если ограничены сети N\, N2,..., N„. Е. Регулярная сеть N = (N\, N2, ..., N„) не жива, если не жива хотя бы одна из со- ставляющих ее сетей N\, N2,..., Nn. Если N\ и N2 — живые регулярные сети, пересе- чение множеств переходов которых содержит не более одного перехода, то живой является сеть (7УЬ N2). Ж. Является ограниченной любая регулярная сеть N=(P, Т, F, Мо), в которой М0(р) * со для любого р g Р. 12.3.9. Иерархические сети Иерархические сети являются обобщением регулярных сетей и служат для моделиро- вания иерархических систем, которые, наряду с неделимыми атомарными компонен- тами, содержат составные компоненты, сами представляющие собой системы. Для определения иерархических сетей и формул класс элементарных формул, т. е. класс символов переходов, разбивается на два непересекающихся подкласса: терми- нальные и нетерминальные символы. Соответственно переходы разделяются на про-
996 Часть II. Применение графов и граф-моделей стые и составные. Терминальные символы и простые переходы трактуются традици- онным образом. Нетерминальные символы обозначают "элементарную" сеть, со- стоящую из единственного составного перехода, имеющего одно входное (головное) место и одно выходное (хвостовое) место, который имеет внутреннюю структуру и является по существу самостоятельной (иерархической) сетью Иерархическая сеть— это сеть, задаваемая структурной формулой, которая пред- ставляет собой формулу сети, построенной из терминальных и нетерминальных сим- волов с помощью операций алгебры регулярных сетей и упорядоченного множества определений нетерминальных символов. Каждое определение имеет вид s:A, где S — нетерминальный символ, а А — формула сети. Следующая структурная формула определяет иерархическую сеть, изображенную на рис. 12.42: (l*(«;(v,w)),l*(/||A)) w:(l(«, b); с) v:(l *h;k) w:((2x,4d;I), (2//) x :(2/; g) Переход t называется внутренним перехода t', а переход /' является объемлющим переходом для перехода /, если либо t содержится в правой части определения пере- хода либо существует такая последовательность переходов t\ = t’, t?,..., tk = t, что k >1, и для любого i, 1 < i = к, переход t, является внутренним переходом перехо- да 4-1 Рис. 12.42. Пример иерархической сети Петри
Глава 12. Прочие граф-модели 997 Дополнительные контекстные ограничения на структурные формулы состоят в сле- дующем. Любой символ, входящий в структурную формулу и не определенный в ней, является терминальным. Каждый нетерминальный символ определяется один раз и не может входить в формулу в правой части своего и последующих определений. Любые два определения нетерминальных символов могут содержать в своих правых частях одинаковые символы, если только они задают переходы, один из которых является внутренним по отношению к другому. Переход Г охватывает переход t, если / является внутренним переходом Г и не суще- ствует в сети такого перехода I", что I" является внутренним переходом Г и объем- лющим для t. Переход t является переходом верхнего уровня, если у t нет объемлюще- го перехода. Иерархическая сеть функционирует, переходя от разметки к разметке, как и регуляр- ная сеть, но правила ее функционирования отличаются от соответствующих правил для регулярной сети ввиду наличия в ней составных переходов. Срабатывание со- ставных переходов не является мгновенным событием, а составным действием. Со- ставной переход может находиться в одном из двух состояний — пассивном и актив- ном. Смена пассивного состояния на активное (или активация составного перехода) и смена активного состояния на пассивное (или его завершение) являются мгновен- ными событиями. Начальное состояние всех переходов— пассивное. Простые пере- ходы также могут быть активны, но их активность мгновенна, и активация совпадает с завершением. Переход t может быть активирован, если он пассивен, охватывающий его переход активен или / является переходом верхнего уровня, для любого места сети р справед- ливо М(р) = F(p, f). Когда составной переход t активируется, происходит смена текущей разметки М на такую разметку М', что М(р) = М(р) — F(p, f) для всех h е Р. Условием завершения составного перехода t служит тот факт, что все его внутренние переходы пассивны и ни один из них не может быть активирован. Когда переход t завершен, происходит смена текущей разметки М на разметку М', при этом М'(р) = Мс(р) для любого внутреннего места р перехода t и М'(р) = М(р) + F(p, t) для всех мест сети, не являющихся внутренними для перехода /. Пусть каждому составному переходу I сопоставлены два символа: /'— активации пе- рехода и t"— завершения перехода. Пусть Т = TX\JT' UT", где Т, — множество про- стых переходов, Т"— множество символов активации и Т"— множество символов завершения составных переходов. В процессе функционирования иерархической сети разметка М может смениться на разметку М' в результате срабатывания простого пе- рехода I, т. е. M[t > М', активирования составного перехода t, т. е. M[t' > М', или за- вершения составного перехода /, т. е. M\t" > М'. Определения достижимых переходов, ограниченности сети и ее живости переносятся естественным образом на иерархические сети. При определении свободных языков иерархических сетей появляются варианты.
998 Часть II. Применение графов и граф-моделей Полным свободным языком L(N) иерархической сети N называется множество всех таких последовательностей т е Т*, что существует достижимая в N разметка М, при- чем Л/(,[т > М. Свободным языком сети W считается проекция L(N) на множество Т„ т. е. множество последовательностей, полученных удалением символов активации и завершением составных переходов в последовательностях из L(N). Помеченная иерархическая сеть имеет дополнительную (частичную) помечающую функцию, которая метит только простые переходы. Обычным образом определяется префиксный и терминальный языки помеченной иерархической сети. А. Любой рекурсивно перечислимый язык может быть порожден помеченной иерар- хической сетью. Таким образом, класс иерархических сетей равномощен классам ингибиторных сетей и сетей с приоритетами. Более того, сети любого из этих трех классов эффективно преобразуются в эквивалентные им сети из двух других классов. 12.4. Графы адресуемых данных Структура данных может рассматриваться как набор элементарных данных вместе с множеством отношений между ними. Такие структуры обычно изображаются орграфами, вершины которых соответствуют элементарным данным, а дуги — существующим между ними соотношениям. С вычислительной точки зрения многие важные свойства структур данных не зависят от конкретного содержания элементарных данных в вершинах структуры. Часто, на- пример, анализ алгоритма, работающего с двумя разными структурами данных, будет основываться только на том факте, что одна из них есть дерево, а другая — решетка. Конечно, существуют структуры данных, анализ которых зависит больше от семан- тики, нежели от синтаксиса. Тем не менее, имеет смысл изучать свойства структур данных, которые зависят только от формы, но не от содержания. Этот подход приво- дит к понятию графа данных. Граф данных получается из структуры данных, если отвлечься от элементарных дан- ных, которые соответствуют вершинам структуры, и сосредоточиться на связях меж- ду ними. 12.4.1. Граф данных Пусть С= {с} есть множество ячеек данных. Хотя на практике это множество всегда конечно, удобно считать его счетным. Пусть далее Л есть конечное множество час- тичных преобразований на С, называемых преобразованиями типа, и Лт есть моноид, порождаемый преобразованиями из Л с помощью операции композиции преобразо- ваний. Будем считать, что для каждой пары ячеек с, d е С существует преобразова- ние Е, е Л’ такое, что Е, (с) = d. Определим теперь граф данных Г = (С, Л) как орграф, у которого множеством вершин служит множество С и между вершинами с и d име- ется дуга (с, ф, если существует преобразование ( е Л такое, что ^(с).
Гпава 12 Прочие граф-модели 999 Ясно, что существование преобразования £ е Лт, переводящего ячейку с в d, соответ- ствует наличию пути из вершины с в вершину d, а наложенное условие на Лт соответ- ствует утверждению, что граф данных всегда сильно связен. Рассмотрим некоторые важные примеры графов данных. Бинарное дерево Т (рис. 12.43). Вершины дерева идентифицированы числами 1, 2, 3,..., а три типа связей представлены следующими преобразованиями над множест- вом N натуральных чисел: о/и) = правый потомок(и) = 2и, о/(н) - левый пото- мок^) =2и+1, л(и) = предок(и) = [и/2]. Преобразование "предок"— единственное, которое определено не везде. Тот факт, что л(1) = [1/2] = 0 g N, означает, что ячейка с номером 1 (корень дерева) не имеет предка. Рис. 12.43. Бинарное дерево Т Рис. 12.44. Бинарное дерево Г1 Бинарное дерево Т* (рис. 12.44). В отличие от бинарного дерева Т преобразование л "предок" заменено преобразованием со "возврат в корень", т. е. со (и) = 1. Бинарное дерево Т может использоваться для реализации словарей на базе АВЛ- деревьев, ВВ-деревьев и других бинарных деревьев сортировки. Бинарное дерево 7м может быть использовано в случае, когда нужно реализовать операцию НАЙТИ в словаре с постоянным множеством слов. Двумерный квадратный граф S2 (рис. 12.45). Вершины идентифицированы натураль- ными числами 1, 2, 3,.., имеется четыре типа связей: аг(и) = правый потомок(и) = 2и, О/(и) = левый потомок(и) = [п/2], и„(п) = верхний потомок(и) = Зи, ot/(«) = нижний потомок(и) = [и/3]. Лестничная структура L2 (рис. 12.46). Множеством вершин служит множество Ах{0,1}, имеется три типа связей:
1000 Часть II. Применение графов и граф-моделей р((п, тп)) = правый сосед((п, т» = (и + 1, т), Х((и, т)) = левый сосед((п, т}) = {п- 1, т), <р((п, т)) = переход((п, /л» = {и, т + 1 (mod 2)>. Рис. 12.45. Двумерный квадратный граф S2 Линейный список £' (рис. 12.47). Множеством вершин структуры служит множество Z целых чисел, имеется два вида связей: p(z) = правый сосед(г) = z + 1, Z(z) = левый сосед(г) = z - 1. Рис. 12.47. Линейный список L1 Пермутационный граф Р (рис. 12.48). Множество вершин есть множество {1, 2, 3}, множество преобразований А содержит следующие элементы: Х|(1)=1, Х,(2) = 3, Х,(3) = 2, Х2(1) = 3, Х2(2) = 2, Х2(3) = 1, Х3(1) = 2, Х3(2) = 1, Х3(3) = 3. Бинарное дерево с мостами 73 (рис. 12.49). Множество вершин есть множество N на- туральных чисел, множество преобразований А есть множество {а,, о/, л, [3,, PJ, где: Or(n) = 2п, Gi(ri) = 2п + 1, л (n) = [n/2], pr(«) = п + 1, если п = 4m (т > 1), Р/(п) = и + 1, если п = 4m+2 (т > 1). Двумерный диагональный квадратный граф S2] (рис. 12.50). Множество вершин есть множество {2п"Зр | р еN'J {0}}, множество преобразований А есть множество {о, л, р}, где: о (п) = 6п, п (п) = п/3, р (п) = п/2.
Глава 12. Прочие граф-модели 1001 Рис. 12.49. Бинарное дерево с мостами Т2 , г.2 Рис. 12.50. Двумерный диагональный квадратный граф St
1002 Часть II. Применение графов и граф-моделей Рис. 12.51. Вариант линейного списка L(2) Вариант линейного списка £(2) (рис. 12.51). Множество вершин есть множество {0} u (Nx{0,l}), множество преобразований Л есть множество {о, л, р], где: а (0) = = (1,0 >, р (0) = (1,1 ), о ((л, m )) = р((л, m )) = (и + 1, т), л((л, m))=^ " если л > 1, если п = 1. Вариант линейного списка с двумя входами £<3) (рис. 12.52). Множество вершин есть множество {«, b} N, множество преобразований Л есть множество {а, л, р}, где: а (а) = о(£) = 1, л (1) = а, р (1) = Ь, о (и) = п + 1, л (л) = р(л) = п - 1. Рис. 12.52. Вариант линейного списка с двумя входами £(3) Вариант бинарного дерева Г3 (рис. 12.53). Множество вершин есть множество {0} <jN, множество преобразований Л есть множество {о/, ог, л}, где: а/(л) = 2п+ 1, оДл) = 2л, п * 0, л(л) = [л/2], л * 0. Рис. 12.53. Вариант бинарного дерева I3
Глава 12. Прочие граф-модели 1003 12.4.2. Реализация графов данных Основная проблема, возникающая при изучении графов данных, есть проблема реа- лизации их в памяти с произвольным доступом. Пусть А есть адресное пространство памяти, т. е. множество адресов. Реализация графа данных (С, А) в А включает в себя: □ приписывание каждой ячейке с е С однозначно определенного адреса из множе- ства Л; □ механизм (функцию) для определения по адресу а е А ячейки с е С и преобразо- вания Е, е Г(с) адреса ячейки Е, (с) (здесь V (с) есть множество преобразований, определенных на с). Данное неформальное определение реализации может быть упрощено, если механизм получения адреса Е, (с) не зависит от с. Так как каждый граф данных допускает такую реализацию, этот тип реализации является отправным для дальнейших исследований. Формально реализация графа данных Г = (С, А) в адресном пространстве А, мощ- ность |Л| которого не меньше числа |С| вершин графа, определяется как пара (г, р) отображений,где: □ г : С -» А — взаимно-однозначное отображение множества С в множество Л; П р : А* ^>Аа— гомоморфизм моноидов, взаимно однозначно отображающий Ат в множество Аа частично определенных преобразований множества А. Таким образом, р(1г) = 1л, и для ц е Ат имеет место равенство р(^ц) = р(^)р(г]). Пара (г, р) должна удовлетворять следующим двум условиям, справедливым для всех с е С и для всех X е А: П Х(с) е Сс> р(Х)(г(с)) е г(С); П если Хе V (с), то г(Х(с)) = р(Х)(г(с)). Отсюда следует, что если (г, р) реализует граф данных Г = (С, А), то граф (/'(С), р(А)) изоморфен Г, и поэтому структурные свойства реализации зависят только от струк- турных свойств реализованного графа данных. Часто полезно предполагать, что г отображает С на А. Реализация (г, р) называется тотальной, если г отображает С взаимно-однозначно на А. 12.4.3. Относительная адресация Известны различные методы реализации графов данных, каждый из которых имеет собственные достоинства и недостатки. Наиболее известной техникой размещения является метод относительной адресации. На неформальном уровне описания этот метод можно представить себе как выделе- ние базового адреса, а представление адресов остальных ячеек (вершин графа) — как смещение относительно базового адреса.
1004 Часть II. Применение графов и граф-моделей Этот механизм обладает рядом практических достоинств. Во-первых, механизм обхо- да фафов, реализованных с помощью относительной адресации, имеет тенденцию к простоте и малому числу просмотров. Во-вторых, "стоимость" эффективных перехо- дов в графе часто более однородна, нежели в методах, использующих "связывания", и во многих практических ситуациях эта стоимость низка. Наконец, при работе с "пол- ными" фафами, такими как плотно заполненные массивы и полные деревья, этот ме- тод имеет тенденцию к более компактному размещению, чем его конкуренты. Однако данный метод имеет и два крупных недостатка. Он склонен расходовать лишнюю память при применении его к неполным графам, а также быть негибким — небольшие изменения в графах данных могут сделать необходимым совершенно дру- гую схему для вычисления смещений. Таким образом, данный метод может исполь- зоваться при реализации алгоритмов, которые меняют только элементарные данные в структуре и не затрагивают связи между ними. Формально реализация (г, р) графа данных Г = (С, Л) в множество А называется реа- лизацией с относительной адресацией, если □ существует выделенный базовый адрес aQ е r(Q; □ существует биективная функция смещения 5 : С —> Q = {юе р (Лт) | со (сл,) е г(С)} такая, что для всех с е С справедливо соотношение r(c) = 5 (с)(а0). Нетрудно заметить, что в реализации с относительной адресацией имеет место зави- симость р (Е,) = г-1 Е, .г. Практически это означает, что при перемещении графа дан- ных в памяти, т. е. при изменении г, нужно изменить и р, что может потребовать больших потерь времени. Однако встречаются и такие графы данных, которые до- пускают "перемещаемую реализацию", где отображение р нечувствительно к пере- мещению графа в памяти. Граф данных Г = (С, Л) называется перемещаемым в адресном пространстве А с |Л| = |С|, если существует ячейка с0 е С и инъективное отображение р0: Лт —> А<:) такое, что для каждого а е А найдется отображение го : С —> Л, что го(с0) = а и (гсп р0) — реализация фафа Г в А. Для описания класса перемещаемых графов введем ряд вспомогательных определе- ний. Важным свойством графов данны х’является его адресуемость, т. е. возможность однозначно указывать адрес любой его вершины с помощью всюду определенной функции а (Г): С —> Лт такой, что □ существует вершина с0, для которой а(с0) = 1(- (1(- есть тождественное преобразо- вание на С); □ для всех X е Л и с е Д(Х) справедливо соотношение а(Х(с)) = Х(а(с)) (здесь Д(Г) есть область определения преобразования X). Функция а (Г) называется адресующей схемой для графа данных Г, а граф Г, допус- кающий адресующую схему, называется адресуемым. Для выявления свойств адресующих схем важное значение имеет такая структурная характеристика графа данных, как корень. Вершина с0 называется корнем графа дан-
Гпава 12. Прочие граф-модели 1005 ных Г = (С, Л), если существует единственное преобразование из Л’, переводящее с0 в любую другую вершину. Граф Г называется корневым, если он имеет хотя бы один корень. Бинарное дерево (см. рис. 12.43) и двумерный квадратный граф (см. рис. 12.45) имеют по одному корню. Бинарное дерево с возвратом 7*1’ (см. рис. 12.44) не имеет корня так же, как и граф перестановок Р (см. рис. 12.48). Лестничная структура (см. рис. 12.46) имеет два корня. Линейный список (см. рис. 12.47) имеет бесконечно много корней. А. Граф Г = (С, Л) адресуем тогда и только тогда, когда он имеет корень. Важным следствием этого утверждения является тот факт, что адресуемость есть свойство моноида преобразований Лт, а не его набора порождающих преобразований. Как следствие получаем, что если А, есть подмоноид моноида Л2, то адресующая схема для графа Г2 = (С, Л2) есть одновременно адресующая схема для Г| = (С, А(). Обратное в общем случае неверно. С точки зрения практики это означает, что пере- ход от графа Г к его транзитивному замыканию сохраняет адресующую схему, так же как и уменьшение числа образующих моноида. Первое повышает эффективность пе- реходов по графу, второе дает более экономное представление. Множество различных адресующих для одного графа разбивается на классы по числу корней. Внутри каждого класса схемы эквивалентны в том смысле, что для любых двух адресующих схем аир найдется единственное преобразование е Л1 такое, что для всех с е С имеет место соотношение а(с) = ^а(Р(с)). Б. Граф данных допускает реализацию с относительной адресацией в том и только том случае, когда он адресуем. В. Граф данных перемещаем только в том случае, когда он адресуем с относитель- ной адресацией', обратное неверно. 12.4.4. Вложения графов Графы данных являются логическими структурами данных в отличие от структур физической памяти. Переход от графов данных к физической памяти на языке теории графов приводит к исследованию вложений одного вида графов в другой. Изоморфным вложением графа G, в G2 называется изоморфизм G| на подграф Н графа G2. Обобщением этого понятия служит гомеоморфное вложение графа G) в граф G2. Говорят, что граф G| гомеоморфно вкладывается в G2, если существует такое взаимно-однозначное отображение у: Vx Г2, что из существования дуги (vi, v2) в Gi вытекает существование пути р в G2 из vp(v,) в y(v2), причем все такие пути являются простыми и не имеют общих вершин. Смысл вложения заключается в упрощении анализа вложенного графа и манипулиро- вания с ним за счет более простой структуры графа-хозяина или надграфа. Например, упрощается хранение сложной структуры данных в памяти, при проектировании БИ- Сов можно воспользоваться более простой технологией и т. д. Степень этого упро-
1006 Часть II. Применение графов и граф-моделей шения зависит от "качества" вложения, оцениваемого с помощью стоимости вложе- ния с(\у), определяемой формулой c(V)= max ^g2(V(v),v|/(v’)) (v,v')eG, где d(^ есть длина кратчайшего пути р из \p(v) в vp(v') в G2. С учетом стоимости задача о вложении формулируется следующим образом. 1. Для данных графов G| и G2 необходимо: • найти вложение G, вС2с минимальной стоимостью; • выяснить, является ли граф G| вложим в G2 со стоимостью < к, где к — за- данная константа. 2. Ставится так же, как и задача 1, но вместо фиксированного графа G2 берется се- мейство графов. Наиболее часто в приложениях встречаются следующие классы графов: □ бинарные деревья; □ решетки (вершинами служат пары i = 1, ...,n,j= 1, ..., т, а дуги соединяют {i,j ) с (£, /) только тогда, когда |/ -к\ + |/ -1| = 1); □ лучи (вершины суть элементы множества {1, ..., и}, а дуги соединяют (i) с (/), ко- гда |/ -у| = 1). О сформулированных задачах в общем случае известно довольно мало, больше из- вестно для случаев, когда вложение производится в луч. Трудности такого вложения выявляет следующее свойство. А. Проблема определения для данного графа G и целого к существования вложения графа G в луч со стоимостью с(\|,) < к является NP-полной. Она остается NP- полной даже в том случае, когда G есть бинарное дерево. Для данного фиксирован- ного к проблема разрешима за время flk)nk+ '. Не известен ни один аналог данного свойства для вложений в бинарные деревья и решетки, хотя имеется большое число областей применения, где желательны именно такие вложения. В специальном случае, когда в луч вкладывается единичный ^/-мерный куб, известен следующий результат Харпера. Б. Любое оптимальное вложение d-мерного единичного куба в луч строится сле- дующим образом, в вершину (1) луча укладывается произвольная вершина куба', если уже уложены вершины куба в вершины (1), ..., (Л), то в {k + 1) укладывается верши- на куба, являющаяся неуложенной вершиной, смежной с вершиной, уложенной в вершину луча с наименьшим номером. Внешнепланарным графом называется планарный граф, который может быть изобра- жен на плоскости так, что все его вершины принадлежат внешней грани.
Глава 12. Прочие граф-модели 1007 В. Любой внешнеплаиарный граф G может быть вложен в бинарное дерево со стоимостью с(\р) < 3 log2(2 max deg(G)) за время, пропорциональное числу ребер графа G. Это свойство имеет далеко идущие последствия для отыскания эффективных вложе- ний большого числа семейств графов в бинарные деревья. Библиографический комментарий Представление в виде упорядоченных бинарных диаграмм определяется путем наложения ог- раничений на бинарные диаграммы решений, введенные Ли [54] и Экерсом [20]. Эти ограни- чения и получаемая в итоге каноничность представления были впервые описаны Фортупом и др. [41]. Бинарные диаграммы решений много лет использовались в качестве абстрактного представления булевых функций. Под названием "программы ветвления" они были тщательно исследованы специалистами по теории сложности вычислений (см., например, Вегенер [76], Мейнел [60]). В своем изложении мы базируемся на работах Брянта [29—31], который ввел понятие OBDD в 1986 году. Дополнительная библиография по этой тематике может быть най- дена в обзоре Мейнела и др [61]. Более общее понятие логического фрагмента [9], которое позволяет представлят ь частичные функции, а также нс только логические, но и другие функ- ции от логических переменных, использовалось при исследовании схем Янова [7, 11]. Проблема нахождения оптимального упорядочения переменных для OBDD является NP- трудной [26, 74] Эвристические методы, позволяющие находить хорошие способы упорядо- чения переменных для OBDD. предложены в работах Фуджита и др. [42]. Малика и др. [58], Джонга и др. [50]. Свойство 12.1.1, А доказано в работе [30], а свойство 12.1.1, В — в работе [28], символьный симулятор COSMOS описан в [37]. Берман [24] и Макмиллан [59] вывели границы для нескольких классов сетей с "ограниченной шириной". Макмиллан [59] обобщил эту технику до древовидного расположения, в котором сеть организована в виде дерева логи- ческих блоков с коэффициентом ветвления b и первичным выходным значением, производи- мым корневым блоком. Вопросы реализации OBDD на рабочих станциях с большой физической памятью рассматри- вались в Брэйсом и др. [27]. Другие исследователи [53, 63] успешно использовали для их реа- лизации векторные операции и достигли хороших результатов при обработке OBDD на муль- типроцессорах с разделенной памятью. Усовершенствованиям базовой структуры OBDD, которые направлены на экономию памяти, посвящен целый ряд работ. Среди них — использование единственного многокорпевого графа для представления всех требуемых функций [29, 51, 62, 67], снабжение дуг метками для обо- значения булевого вычитания [27, 51, 57, 62] и обобщение понятия областей с конечным чис- лом состояний [71]. Ряд авторов рассматривал методы, основанные на тех же общих принци- пах, что и OBDD, но с менее строгими ограничениями структуры данных [22, 25, 32, 40, 51, 52, 76]. Возможности улучшения процессов обработки с использованием OBDD на основе идеи "ленивого" (или "отложенного") исполнения рассматривались в [19, 38]. Сведения об отношениях в том или ином объеме включаются в большинство книг по теорети- ко-множественной и кибернетической тематике [1,2]. Несколько особняком в этом стоит ис- пользование отношений в теории и практике реляционных баз данных [4]. В книге [10] под- робно рассматриваются решетки, полурешетки и подрешетки. Связь чу-множеств и графов рассмотрена в статье [56]. Что касается размерности чу-множеств, то здесь следует указать на обзор [72]. Разд. 12.2.6 написан по материалам статьи [47]. -аразд. 12.2.7 подготовлен по мате-
1008 Часть II. Применение графов и граф-моделей риалам статьи [36]. С общей проблемой мониторинга программ можно познакомиться в обзоре [66], с различными аспектами мониторинга параллельных программ— в [33—35, 45]. К дан- ной тематике близки работы по отладке параллельных программ [39] (см. также [10] и список литературы при ней). На основе статьи [75] написан разд. 12.2.8. Там же можно найти ссылки на работы, связанные с применениями ННГ-замыканий для диспетчеризации мультиметодов. Следует указать на очень важную область исследований, связанную с классификацией неори- ентированных графов на базе частичных порядков. В разд. 12.2.3 были введены понятия гра- фов сравнимости, хордальных и интервальных графов. С их помощью можно определить большое число классов графов, обладающих тем свойством, что некоторые ЛД-полные в об- щем случае задачи на этих классах решаются за полиномиальное время. Данным вопросам посвящено большое число публикаций, на некоторые из них мы хотим обратить внимание. В работе [46] показано, что многие интересные классы графов могут быть охарактеризованы с использованием свойств хордальносги графа или его дополнений и транзитивной ориенти- руемости графа или его дополнения. Например, граф — расщепляемый (split) тогда и только тогда, когда он и его дополнение— хордальные графы; граф— перестановочный (permutation) тогда и только тогда, когда он и его дополнение — графы сравнимости; граф — интервальный тогда и только тогда, когда граф — хордальный, а его дополнение есть граф сравнимости. Хордальность графа распознается за линейное время, а тот факт, что граф есть граф сравнимости, устанавливается за время О(и2376). К важным подклассам хордальных графов относятся интервальные графы, расщепляемые, строго хордальные, хордальные графы сравнимости, двойственно хордальные, дважды хор- дальные и др. Эти классы допускают эффективные алгоритмы распознавания, в основе кото- рых лежат алгоритмы построения специальных нумераций вершин. Важна с алгоритмической точки зрения связь хордальных графов с так называемыми частичными к-деревьями (partial A-tree). Эта связь исследована в [21] (см. также [43]). Еще одно важное направление исследований— связь частичных порядков с построением транзитивного замыкания графа. Ранние алгоритмы распознавания таких частичных порядков, как интервальный порядок, свободный от циклов порядок, порядки размерности 2, ^сво- бодные порядки и др. предполагали, что на входе имелось либо транзитивное замыкание гра- фа, либо транзитивная редукция. Важным исключением является алгоритм распознавания па- раллельно-последовательных частичных порядков. Если же на входе имеем произвольный бесконтурный граф, представляющий какой-нибудь частичный порядок, и мы используем об- щий алгоритм построения транзитивного замыкания, то трудоемкость алгоритмов распознава- ния будет полностью определяться трудоемкостью построения транзитивного замыкания. Для интервальных порядков, свободных от циклов и A-свободных порядков, известен алгоритм построения транзитивного замыкания с трудоемкостью О(п + тф где т,— число дуг в транзи- тивном замыкании соответствующего графа. Этот факт понижает трудоемкость распознавания указанных частичных порядков при произвольном графе на входе до О(п + т,). Для двумерных частичных порядков в [55] предложен алгоритм с трудоемкостью (Э(и2). Впервые сети Петри предложил Карл Адам Петри в своей докторской диссертации в 1962 году, но большинство последующих работ в этом направлении было основано на итого- вом отчете А. Хольта и его коллег по проекту "Теория информационных систем", в котором была переведена на английский язык и значительно расширена диссертация Петри. Кроме то- го, среди первых публикаций важную роль сыграла работа Хольта и Коммонера |48], а также доклад Петри [65] на конгрессе ИФИП с изложением идей, представленных в диссертации. Систематическое изучение свойств сетей Петри и возможности применения их для решения прикладных задач, в основном задач, связанных с моделями и средствами параллельной обра- ботки информации, началось на рубеже 60-х и 70-х годов XX века.
Гпава 12. Прочие граф-модели 1009 К сожалению, многие исследования по сетям Петри доступны только в виде технических отче- тов тех институтов, где они были выполнены, а в журналах появляется только их конспектив- ное изложение. Основным источником начальных работ по сетям Петри были работы, выпол- ненные в Массачусетском технологическом институте (МТИ, США). Первоначально эти отче- ты были выпущены Проектом МАС. Проект МАС изменил свое название и теперь именуется Лабораторией вычислительной техники. Другим важным источником научно-исследователь- ских отчетов является Институт исследований информационных систем при Обществе матема- тики и обработки данных в Бонне, Германия. Книга [8] содержит аннотированную библиогра- фию, включающую более 300 журнальных публикаций, отчетов и докладов на конференциях, опубликованных до 1981 года. Базовая англоязычная (и немецкая) терминология по сетям Петри сейчас устоялась, хотя и употребляются разные варианты одинаковых или близких понятий. Попытка провести ее даль- нейшую унификацию сделана в [44]. Представленный в данной главе материал по сетям Петри во многом основан на книге [12]. Дальнейшее знакомство с сетями Петри можно начать с об- зоров [23, 64], а также книг [3, 6, 12, 17, 49]. Описание графов данных дано по работе [5], в которой кратко были рассмотрены основопола- гающие для данной теории результаты Розенберга [63—71]. Список литературы 1. Биркгоф Г. Теория решеток. — М.: Наука, 1984. 2. Биркгоф Г., Барти Т. Современная прикладная алгебра. — М.: Мир, 1976. 3. Вербицкайте И. Б. Семантические модели в теории параллелизма. — Новосибирск: Изд-во ИСИ СО РАН, 2000. 4. Дейт К. Введение в системы баз данных. — М.:'Наука, 1980. 5. Евстигнеев В. А. Графы адресуемых данных // Комб.-алгебраические методы в приклад- ной математике. — Горький: Изд-во ГГУ, 1986. — С. 39—60. 6. Евстигнеев В. А., Касьянов В. Н. Сводимые графы и граф-модели в программировании. — Новосибирск: Изд-во ИДМИ, 1999. 7. Ершов А. П. Введение в теоретическое программирование. — Новосибирск: Наука, 1977. 8. Калбертсон Дж. Т. Математика и логика цифровых устройств. — М.: Просвещение, 1965. 9. Касьянов В. Н., Сабельфельд В. К. Сборник заданий по практикуму на ЭВМ. — М.: Нау- ка, 1986. 10. Колосова Ю. И. Реализация и анализ причинного порядка событий в распределенных вы- числениях. — Новосибирск, 1995. — (Препринт ВЦ СО РАН, № 1046). 11. Котов В. Е. Введение в теорию схем программ. — Новосибирск: Наука, 1978. 12. Котов В. Е. Сети Петри. — М.: Наука, 1984. 13. Кук Д., Бейз Г. Компьютерная математика. — М.: Наука, 1990. 14. Куратовский Л., Мостовский А. Теория множеств. — М.: Мир, 1970. 15. Липский В. Комбинаторика для программистов. — М.: Мир, 1988. 16. Оре О. Теория графов. — М.: Наука, 1968. 17. Питерсон Дж. Теория сетей Петри и моделирование систем. — М.: Мир, 1984.
1010 Часть II. Применение графов и граф-моделей 18 Скорняков Л А. Элементы теории структур. — М.: Наука, 1970. 19. Abelson, Н., Sussman, G. J. and Sussman, J. Structure and interpretation of computer pro- grams. — MIT Press, Cambridge, Mass, 1988. — P. 261—264 20. Akers S. B. Binary decision diagrams // IEEE Trans. Comput. — 1978. — Vol. C-27, N 6. — P. 509—516. 21. Arnborg S., Corneil D. G., Proskurowski A. Complexity of finding embeddings in a /-tree// SIAM J. Alg. Disc. Math. — 1987. — Vol. 8, N 2. — P. 273—284. 22. Ashar P., Devadas S., Ghosh A. Boolean satisfiability and equivalence checking using general binary decision diagrams // The International Conference on Computer Design — IEEE, New York, 1991. — P. 259—264. 23. Baer J. A survey of some theoretical aspects of multiprocessing// Computing Surveys.— 1973.— Vol. 5,N 1,—P. 31—80. 24. Berman C. L. Ordered binary decision diagrams and circuit structure // The International Con- ference on Computer Design. — IEEE, New York, 1989 — P. 392—395. 25. Blum M. W., Chandra A. K. Equivalence of free Boolean graphs can be decided probabilisti- cally in polynomial time // Inf. Process. Lett. — 1980. — Vol. 10, N 2. — P. 80—82. 26. Bollig B., Wegener I. Improving the variable ordering of OBDDs is NP-complete // IEEE Trans. Computers. — 1996. — Vol. 45. — P. 993—1002. 27. Brace K. S., Bryant R. E. and Rudell R. L. Efficient implementation of a BDD package. In Pro- ceedings of the 27th ACM / IEEE Design Automation Conference. — ACM, New York, 1990,—P. 40—45 28 Brayton R. К , Hachtel G. D., McMullen С. T., Sangiovanm-Vincentelli A. L Logic Minimiza- tion Algorithms for VLSI Synthesis. — Kluwer Academic Publishers, Boston, 1984 29. Bryant R. E. Graph-based algorithms for Boolean function manipulation // IEEE Trans. Com- put. — 1986. — Vol. C-35, N 6. — P. 677—691. 30 Bryant R. E. On the complexity of VLSI implementations and graph representations of Boolean functions with application to integer multiplication // IEEE Trans. Comput — 1991 — Vol. 40. N2. — P. 205—213. 31. Bryant R. E. Simbolic Boolean manipulation with ordered binary-decision diagrams// ACM Computing Surveys. — 1992. — Vol. 24, N 3. — P. 293—318. 32. Burch J. R. Using BDDs to verify multipliers // Proceedings of the 28th ACM / IEEE Design Automation Conference. — ACM, New York, 1991. — P. 408—412. 33. Cheng J. A classification on tasking deadlocks // ASM Ada Letters. — 1990. — Vol. 10, N 5. — P. 110—127. 34. Cheng J., Araki K., Ushijima K. Tasking communication deadlocks in concurrent Ada pro- grams // ACM Ada Letters. —1988. — Vol. 8, N 5. — P. 61- 70. 35. Cheng J., Ushijima K. Detecting tasking communication deadlocks in concurrent Ada pro- grams // Proc. Int. Computer Sci. Conf. ’88. — P. 138—145. 36. Cheng J., Ushijima. K. Partial order transparency as a tool to reduce interference in monitoring concurrent systems // Distributed Environments. — Springer-Verlag, 1991. — P 156—171. 37. Cho K. and Bryant R. E. Test pattern generation for sequential MOS circuits by symbolic fault simulation // Proceedings of the 26th ACM / IEEE Design Automation Conference. — ACM, New York, 1989. — P. 418—423.
Гпава 12. Прочие граф-модели 1011 38, Deguchi Y., Ishiura N. and Yajima S. Probabilistic CTSS: Analysis of timing error probability in asynchronous logic circuits // Proceedings of the 28th ACM / IEEE Design Automation Confer- ence. — ACM, New York, 1991. — P. 650—655. 39. Fidge C. J. Partial orders for parallel debudding// SIGPLAN Notices.— 1989.— Vol. 24, N 1. —P. 183—194. 40. Finkbeiner B. Language containment checking with nondeterministic BDDs // Lecture Notes in Computer Science. — 2001. — Vol. 2031. — P. 24—38. 41. Fortune S., Hopcroft J., Schmidt E. M. The complexity of equivalence and containment for free single variable program schemes // Lecture Notes in Computer Science, — 1978. — Vol. 62. — P. 227—240. 42. Fujita M., Fujisawa H. and Kawato N Evaluations and improvements of a Boolean comparison program based on binary decision diagrams // The International Conference on Computer-Aided Design. — IEEE, New York, 1988. — P. 2—5. 43. Garbe R. Tree-width and path-width of comparability graphs of interval orders // Lecture Notes Comp. Sci. — Springer-Verlag. — 1995. — Vol. 903. — P. 26—-27. 44. Genrich H. J., Stankiewicz-Wiechno E. A dictionary of some basic notions of net theory // Lec- ture Notes in Computer Science. — 1980. — Vol. 84, — P. 519—531. 45. German S. M. Monitoring for deadblock and blocking in Ada tasking // IEEE Trans. Soft. Eng. — 1984 — Vol. SE-10, N 6. — P. 764—777. 46. Golumbic M. C. Algorithmic graph theory and perfect graphs. —N.Y.: Academic Press, 1980. 47. Halib M., Nourine L. Bit-vector encoding for partially ordered sets // Lecture Notes Comp. Sci.—1994 —Vol. 831. —P. 1—12. 48. Holt A., Commoner F. Events and conditions // Report of Project MAC Conf, on Concurrent Systems and Parallel Computation. — MIT, Cambridge, 1970. —P. 3—52. 49. Jensen K. Coloured Petri Nets: Basic Concepts, Analysis Methods and Practical Use.— Springer Verlag, 1997, —Vol. 1,2,3. 50. Jeong S.-W., Plessier B., Hachtcl G. D. and Somenzi F. Variable ordering and selection for FSM traversal // The International Conference on Computer-Aided Design. — IEEE, New York, 1991, —P. 476—479. 51. Karplus K. Using if-then-else DAGs for multi-level logic minimization // Advance Research in VLSI. — MIT Press, Cambridge, Mass., 1989. — P. 101—118. 52. Katayama T„ Ochi H., Tsuda T. An algorithm for generating genetic BDDs // IEICE Trans. Fundamentals. — 2000. — Vol. E88-A, N. 12. — P. 2505—2512. 53. Kimura S., Clark E. M. A parallel algorithm for constructing binary decision diagrams // The In- ternational Conference on Computer Design. — IEEE, New York, 1990. — P. 220—223'. 54. Lee C. Y. Representation of switching circuits by binary-decision programs H Bell System Tech. J. — 1959. — Vol 38, N 4. — P. 985—999. 55. Ma Т.-H., Spinrad J. P. Avoiding matrix multiplication // Lecture Notes Comp. Sci. — 1991. — Vol. 494, —P. 61—71 56. Ma Т.-H., Spinrad J. P. Cycle-free partial orders and chordal comparability graphs // Order. — 1991, —Vol. 8, —P. 49—61. 57. Madre J. C. and Billon J. P. Proving circuit correctness using formal comparison between expected and extracted behaviour// Proceedings of the 25th ACM / IEEE Design Automation Conference. — ACM, New York, 1988. — P. 205—210.
1012 Часть II. Применение графов и граф-моделей 58. Malik S., Wang A., Brayton К. К. and Sangiovann-Vincentelli A. Logic verification using bi- nary decision diagrams in a logic synthesis environment// The International Conference on Computer-Aided Design. — IEEE, New York, 1966. — P. 6—9. 59. McMillan K. L. Symbolic model checking: An approach to the state explosion problem. PhD thesis. School of Computer Science, Carnegie-Mellon Univ, 1992. 60. Meinel C. Modified branching programs and their computational power// Lecture Notes in Comp. Sci. — 1990. — Vol. 370. 61. Meinel C., Stangier C. Data structure for Boolean function. BDDs— foundations and aplica- tions // Lecture Notes in Computer Science. — 2001. — Vol. 370. — P. 61—78. 62. Minato S., IshiuraN. and Yajima S. Shared binary' decision diagram with attributed edges for ef- ficient Boolean function manipulation // Proceedings of the 27th ACM / IEEE Design Automa- tion Conference. — ACM, New York, 1990. — P. 52—57. 63. Ochi H., Ishiura N. and Yajima S. Breadth-first manipulation of SBDD of function for vector processing// Proceedings of the 28th /\СМ I IEEE Design Automation Conference. — ACM, New York, 1991. —P. 413—416. 64. Peterson J. Petri Nets // Computing Surveys. — 1977. — Vol. 9, N 3. — P. 223—252. 65. Petri C. Fundamentals of a theory of asynchronous information flow// Information processing 62: Proc, of the 1962 Congress. — Amsterdam: North—1 lolland, 1962. — P. 386—390. 66. Plattner B., Nievergelt J. Monitoring program execution: A survey// IEEE Computer.— 1981,—Vol. 14, N IL —P. 76—93. 67. Reeves D. S. and Irwin M. J. Fast methods for switch-level verification of MOS circuits // IEEE Trans. CAD / IC CAD. — 1987. — Vol. 6, N 5. — P. 766—779. 68. Rosenberg A. L. Addressable data graphs // J. ACM. — 1972. — Vol. 12, N 2. — P. 309—340. 69. Rosenberg A. L. Data encodings and their costs// Acta Informatica.— 1978.— Vol. 9.— P. 273—292. 70. Rosenberg A. L. Data graphs and addressing schemes // J. of Computer and System Sci. — 1971, —Vol. 5, —P. 193—238. 71. Rosenberg A. L. Issues in the study of graph embeddings// Lecture Notes in Comp. Sci.— 1981, —Vol. 100, —P. 150—176. 72. Spinrad J. Dimension and algorithms// Lecture Notes Comp. Sci.— 1994.— Vol. 831.— P. 33—52. 73. Srinivasan A., Kam T., Malik S. and Brayton R. K. Algorithms for discrete function manipula- tion // The International Conference on Computer-Aided Design. — IEEE, New York, 1990. — P. 92—95. 74. Tani S., Hamaguchi K., Yajima S. The complexity of the optimal variable ordering problems of shared binary decision diagrams// Lecture Notes in Comp. Sci.— 1993.— Vol. 762.— P. 389—398. 75. Turau F„ Chen W. GLB-closures in directed acyclic graphs and their applications // Lecture Notes Comp. Sci. — 1995.— Vol. 903. —P. 121—129. 76. Wegener I. On the complexity of branching programs and decision trees for clique functions// J. ACM. — 1988. — Vol. 35, N 2. — P. 461—471.
ЧАСТЬ III Приложения Приложение!. РАМ, ВУ-язык и список Л/Р-полных задач Приложение 2. Характеристики размещений графов
Приложение 1 посвящено вопросам представления алгоритмов и "перебор- ным" (/VP-полным) задачам. Наряду с введением понятия Л'Р-пол ноты и рассмотрением списков /VP-полных задач из различных областей програм- мирования и информатики, описываются абстрактная модель вычислитель- ной машины с произвольным доступом к памяти — равнодоступная адрес- ная машина (РАМ) и язык высокого уровня (ВУ-язык), используемые в кни- ге для представления и анализа алгоритмов. В приложении 2 даются характеристики размещений графов, включая размер области размещения, оценки величины углов, число сгибов и пр.
ПРИЛОЖЕНИЕ 1 РАМ, ВУ-язык и список Л/Р-полных задач Найдется немного научных терминов, так быстро завоевавших широкую известность, как понятие 'WP-полная задача". За короткий промежуток времени с момента введе- ния этого понятия С. Куком в начале 70-х годов XX века оно стало символом тех трудностей, которые встречаются на пути создания достаточно общих и эффективных методов решения задач дискретной математики. Неудачи, постигшие многочисленных исследователей на этом пути, привели к необ- ходимости анализа сложности алгоритмов и задач. Первые результаты о трудноре- шаемости задач — полученные А. Тьюрингом около 40 лет назад и ставшие уже классическими результаты о неразрешимости ряда задач, для которых вообще не су- ществует алгоритмов их решения. Например, он доказал, что невозможно указать алгоритм, который по произвольной программе определял бы, остановится ли эта программа на произвольно заданном входе или нет. В настоящее время известно большое число других (алгоритмически) неразрешимых задач из разных разделов дискретной математики. К ним относится, например, задача выяснения тривиально- сти конечно-порожденных групп, десятая задача Гильберта (разрешимости в целых числах полиномиальных уравнений), ряд задач о покрытии области равными облас- тями и многие другие. На практике, однако, мы не можем довольствоваться констатацией того, что данная задача является разрешимой. Нам, как правило, нужны алгоритмы, предъявляющие при своем выполнении разумные требования к ресурсам используемых вычислитель- ных устройств. Вместе с тем далеко не все разрешимые задачи являются реально раз- решимыми, и существует феномен труднорешаемых разрешимых задач. Первые примеры труднорешаемых разрешимых задач были получены в начале 60-х годов в работах Дж. Хартманниса и Р. Стирнза по "иерархии" сложности. Однако их примеры включали только "искусственные" (специально построенные) задачи. Толь- ко в начале 70-х А. Мейеру, Л. Стокмейеру, М. Фишеру, М. Рабину и ряду исследова- телей удалось показать, что некоторые "естественные" разрешимые задачи трудно- решаемы. Было доказано существование для любого к таких труднорешаемых задач, 2" временная сложность решения которых больше чем 2 , где к — высота башни сте- пеней, ап — размер входа задачи.
1016 Часть III. Приложения Оказалось, что к классу труднорешаемых задач относится большое число изучавших- ся ранее задач из теории автоматов, теории формальных языков, математической ло- гики и других разделов дискретной математики. Причем эти задачи не могут быть эффективно (за полиномиальное время) решены даже с помощью недетерминирован- ного вычислительного устройства, обладающего способностью параллельно выпол- нять неограниченное количество независимых вычислений. Все известные в настоящее время задачи, труднорешаемость которых доказана, попа- дают в один из классов: они либо вовсе неразрешимы, либо труднорешаемы даже на недетерминированном вычислительном устройстве. Вместе с тем большинство пред- ставляющихся труднорешаемыми практических задач дискретной математики лежит вне этих классов и может быть решено за полиномиальное время с помощью неде- терминированной машины. Это так называемые переборные задачи. Переборная задача характеризуется экспо- ненциальным множеством вариантов, среди которых нужно найти решение, и может быть разрешена алгоритмом полного перебора. Так, в задаче о выполнимости логиче- ских формул решение можно отыскать среди 2"' булевских векторов длины ш, где m — число переменных формулы, и, перебрав это экспоненциальное множество век- торов при вычислении значения формулы, мы обязательно решим задачу. Перебор- ный алгоритм имеет экспоненциальную временную сложность и может хорошо рабо- тать на практике для небольших размеров задачи. Но с ростом размера задачи число вариантов быстро растет, и задача становится практически неразрешимой рассмот- ренным методом перебора. Поэтому в конечной области аналогом алгоритмической неразрешимости является необходимость перебора экспоненциального числа вариантов, а аналогом разреши- мости— существование алгоритма решения задачи за полиномиальное время на де- терминированном вычислительном устройстве. При этом ЛР-полные задачи являются эталоном сложности класса переборных задач. На центральный вопрос, можно ли исключить перебор при решении дискретных задач, можно ответить либо построив полиномиальный алгоритм решения одной из УР-полных задач, либо доказав невоз- можность построения эффективного алгоритма для этой задачи. До настоящего вре- мени эта важная проблема дискретной математики остается открытой. В данном приложении вводится понятие УР-полной задачи на базе так называемой равнодоступной адресной машины (РАМ), являющейся хорошим приближением к классу реальных вычислительных машин. Описывается язык высокого уровня (ВУ- язык), использованный в книге для представления алгоритмов, а также приводится обширный список УР-полных задач. 1.1. РАМ и понятие /VP-полноты Все известные в настоящее время реалистические модели ЭВМ (в их детерминиро- ванном и недетерминированном вариантах) эквивалентны относительно полиноми- альной временной сложности. Можно ожидать, что и любая иная "разумная" модель ЭВМ будет эквивалентна в указанном смысле всем перечисленным моделям.
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1017 Под словами "разумная модель" главным образом имеется в виду то, что объем рабо- ты, выполняемой машиной в единицу времени, ограничен (сверху) полиномом. Так, например, модель, обладающая способностью выполнять параллельно произвольно много операций, не будет считаться "разумной", и в действительности ни одна из су- ществующих (или проектируемых) ЭВМ не обладает подобным свойством. Во вся- ком случае, если ограничиться рассмотрением стандартных моделей реальных ЭВМ, то класс труднорешаемых задач не будет зависеть от выбора конкретной модели, и такой выбор можно осуществлять, исходя из интересов дела и не уменьшая при этом сферы применимости полученных результатов. В данном разделе рассматривается РАМ — одна из основных моделей вычислений, используемых в теории сложности вычислений, формализуется ряд интуитивных по- нятий, возникающих при решении задач-дискретной математики, таких как, напри- мер, "задача", "алгоритм", "сложность", вводится понятие АР-полноты и обсуждают- ся методы доказательства /VP-полноты конкретных дискретных задач. 1.1.1. Равнодоступная адресная машина Равнодоступная адресная машина (РАМ) — математическая модель вычислений, ко- торая является хорошим приближением к классу обычных, традиционных вычисли- тельных машин с точки зрения отражения затрат времени и памяти при представле- нии данных и алгоритмов, целиком помещающихся в оперативной памяти. РАМ моделирует вычислительную машину с одним сумматором, в которой команды программы не могут изменять сами себя. Она состоит из входной ленты, с которой она может только считывать, выходной ленты, на которую она может только записы- вать, и памяти (рис. П1.1). Рис. П1.1. Равнодоступная адресная машина Входная лента РАМ — это последовательность клеток, содержащих записи целых чисел и доступных для считывания по одной в соответствии с их упорядоченностью. Выходная лента состоит из неограниченной последовательности клеток, которые вначале все пусты; при выполнении команды записи происходит печать целого числа в первой свободной клетке выходной ленты. Память РАМ — это последовательность подряд пронумерованных ячеек, каждая из которых способна хранить двоичную запись произвольного целого числа. Обращение к значению, хранимому в некоторой ячейке, осуществляется по адресу (номеру) этой
1018 Часть III. Приложения ячейки. Ячейка с номером 0 называется сумматором. Адресация может быть не толь- ко абсолютной, когда явно указывается номер ячейки, но и косвенной. При косвенной адресации указывается адрес некоторой другой ячейки (называемой ссылкой, или указателем), содержимое которой рассматривается в качестве абсолютного адреса адресуемой ячейки. Состояние памяти — это отображение IV адресов в двоичные слова, сопоставляющее каждому адресу 5 то слово ^(s), которое хранится (содержится) в ячейке с адресом s. Программа— это конечная последовательность команд, занумерованных числами 1, 2, 3,..., /. Счетчик команд — это переменная, принимающая значение из множества неотрицательных целых чисел. Состояние вычисления (конфигурация) — это четверка (х, W, к, у), где х — непрочи- танная часть входной ленты, W— состояние памяти, к— значение счетчика команд, ay — заполненная часть входной ленты. Выполнение РАМ-программы начинается с выполнения ее первой команды, нормаль- но завершается выполнением команды останова и описывается протоколом выполне- ния — последовательностью конфигураций, в которой конфигурация (х, IV, I, е), где х — вход, е — пустая цепочка и IV(k) = 0 для любого к, является первой (начальной), а каждая следующая конфигурация, если она имеется, получается из текущей выполне- нием команды, номер которой указан в текущей конфигурации. Конфигурация, в ко- торой счетчик команд равен нулю (ошибочная конфигурация) или номеру команды останова, может быть только последней (заключительной) конфигурацией протокола выполнения. Если выполнение РАМ-программы нормально завершается, то его ре- зультат— запись на выходной ленте, находящейся слева от печатающей головки. Каждая команда РАМ имеет имя (код операции) и операнд. Операнд может быть од- ного из следующих типов: "=1" — означает само число I и называется литералом', "i"— содержимое ячейки i; "*/"— используется для косвенной адресации, т. е. зна- чением операнда служит содержимое ячейки, адрес которой имеется в ячейке с номе- ром I. Обозначая через У(а) значение операнда а, получаем: К(=0 = I; E(i) = IV(i) и K(*z) = IV(IV(i)), где IV—-текущее состояние памяти. Набор команд РАМ традиционен для реальных ЭВМ и состоит из следующих групп: □ команды считывания и запоминания'. => а, где а имеет вид "=/" или — запоми- нает число, равное текущему содержимому сумматора (обозначим его через А, т. е. (Р(0) = А), в ячейке, адрес которой равен С(а); "<= а" — присваивает сумма- тору значение У(а); □ арифметические и логические команды'. [+J а, 0 а, Ц а — присваивают сумматору значения А + V(a), A- V(a), A *У(а) соответственно; Ц а, Ц а, [>| a, |<j а, § а, § а — присваивают сумматору значения А = У (a), А У (a), А > У(а), А < У(а), А < У(а), А > У(а) соответственно; 0 а — присваивает сумматору целую часть от деления А на У(а), если У(а) Ф 0, и присваивает счетчику команд ноль, если У (а) = 0; 0 а, 0 а, 0 а — присваивают сумматору значения Д V К(д), А Л К(я), соответ- ственно;
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1019 □ команды перехода'. |НА| а— присваивает счетчику команд значение У(а); |пер| = /— присваивает счетчику команд значение /, если А— это истинное зна- чение; □ команды ввода и вывода: |ВВОД] а, где а имеет вид "=/" или "Г — присваивает ячейке с адресом У(а) содержимое доступной клетки входной ленты либо при- сваивает ноль счетчику команд, если уже вся лента прочитана; [BblBOJlj а — печа- тает на выходную ленту значение Е(о); команда останова: |СТОП|-—завершает исполнение программы. Предполагается, что, если это не оговорено особо, каждая команда при своем выпол- нении увеличивает значение счетчика команд на единицу, если она не последняя в программе, а последняя присваивает счетчику команд ноль. Например, программа, изображенная на рис П1.2, осуществляет нахождение наи- большего общего делителя двух целых чисел. Метка отделяется от команды двоето- чием, а команды РЛМ-программы перечисляются через точку с запятой. 1 : |ВВОД| = 1, 4'02; 7:02; 10:02; 13: <=2; 16.|на|=3; 2 . |ВВОД| = 2; 5 |ПЕР|= 17; 8 : |ПЕР | = 13; 11: =>=1; 14:01; 17:|ВЫВОД| = 1; 3:<=1; 6: <=1; 9: <= 1; 12: |НА| =3; 15: => = 2, 18.|СТОП|. Рис. П1.2. Пример РАМ-программы 1.1.2. Вычислительная сложность РАМ-программ Имеются два подхода к определению времени, необходимого для выполнения команд РАМ, и объема памяти, используемого каждым регистром РАМ. При равномерном весовом критерии считается, что каждая РАМ-команда затрачива- ет одну единицу времени и каждый регистр использует одну единицу памяти. Если не оговорено противное, то сложность РАМ-программы будет измеряться в соответст- вии с равномерным весовым критерием. Логарифмический весовой критерий учитывает ограниченность размера реальной ячейки памяти в ЭВМ и основывается на предположении, что объем памяти, необхо- димый для хранения значения, равен длине двоичного представления этого значения (т. е. для целого числа п > 0 требуется /(и) = Llog2 nJ + I единиц памяти), а время ис- полнения команды пропорционально длине ее операндов (например, время команды <= i равно /(0, команды => i— + /(0, а команды 0 */— /(Ж(0)) + /(^(0) + + /(^(^(0)).
1020 Часть III. Приложения Временная сложность в худшем случае (или просто временная сложность) РЛ Со- программы— это функция fmax(n), равная наибольшей (по всем входам размера п) из сумм времен, затраченных на каждую сработавшую команду при обработке одного входа размера и. Временная сложность в среднем — это среднее faw(n), взятое по всем входам размера п, тех же самых сумм. Временная сложность в лучшем случае — это функция fmin(ri), равная наименьшей (по всем входам размера п) из сумм времен, затраченных на каждую сработавшую команду при обработке одного входа разме- ра п. При равновероятном появлении входов значение faw{n) равно сумме времен, затра- ченных на каждую сработавшую команду при обработке всех входов размера и, де- ленной на количество входов размера п. Такие же понятия определяются для емкостной сложности, только вместо "времен, затраченных на каждую сработавшую команду", надо подставить в определение фра- зу: "емкость всех регистров, к которым было обращение". Обычно рассматривается поведение указанных сложностных функций в пределе при увеличении размера входа, поскольку именно асимптотическая сложность алгоритма определяет в итоге размер задач, которые можно решить этим алгоритмом. Для опи- сания асимптотического поведения сложностных функций используется следующий формализм. Говорят, что функция fn) не больше по порядку, чем g(n) (обозначение fn) = O(g(ri))), если существует такая константа с > 0, что почти для всех п (т. е. для всех, кроме конечного множества, значений п) справедливо fn) < c-g(n). Функция fn) не меньше по порядку, чем g(n) (обозначение fn) = Q(g(«))), если существует такая константа с > 0, что fn) > c-g(n) для почти всех п. ФункцииДл) и g(n) одного и того же порядка (обозначения fri)= © (g(n)) или fn)~g(ri)), ecnnfn) = O(g(n)) nfn) = fi(g(n)). 1.1.3. Свойства РАМ, связь PAM с другими моделями вычислений Пусть X], х2,..., х„— целые числа, находящиеся в п первых клетках входной ленты, и пусть программа Р записывает у в первую клетку выходной ленты, а затем через некоторое время останавливается. Тогда говорят, что Р вычисляет функцию fx\, ...,х„) =у. А. Множество РАМ-программ вычисляет класс частично рекурсивных функций. Пусть на входной ленте находится цепочка s=xi,x2, —,хп в алфавите {1,2,..., г}, причем символ х, расположен в первой клетке, х2— во второй и т. д., а в (и+1)-й клетке расположен 0 — символ, который будет использоваться в качестве концевого маркера. Входная цепочка s допускается РАМ-программой Р, если Р прочитывает все ее символы и концевой маркер, пишет 1 в первой клетке выходной ленты и оста- навливается. Языком, допускаемым программой Р, называется множество всех цепо- чек (слов), допускаемых ею.
Приложение 1. РАМ, ВУ язык и список ПРполных задач 1021 Б. Язык допускается некоторой РАМ тогда и только тогда, когда он рекурсивно перечислим. Язык допускается РАМ, останавливающейся на всех входах, тогда и только тогда, когда он рекурсивен. Модель вычислительной машины, получившая название равнодоступной адресной машиной с хранимой программой (РАСП), отличается от РАМ лишь тем, что ее про- грамма находится в памяти и может изменять себя, В. Как при равномерном, так и при логарифмичерком весах команд для любой РАМ- программы (соответственно РАСП-программы) с временной сложностью Т(п) су- ществует такая постоянная к, что найдется эквивалентная РАСП-программа (со- ответственно РАМ-программа), временная сложность которой не превосходит к-Т(п). РАМ с логарифмическим весом и машины Тьюринга (МТ) полиномиально связаны. При равномерном весе нет полиномиальной связи между РАМ и МТ, хотя любую МТ с временной сложностью Т(п) > п можно промоделировать некоторой РАМ за время О(Т(п)). Приведем затраты времени, требуемые машине А для моделирования работы алго- ритма сложности Т(п) на машине С; 1 МТ— машина Тьюринга с одной лентой, К МТ — машина Тьюринга с К лентами. Таблица П1.1.Связь различных моделей вычисления Моделируемая машина в Моделирующая машина А 1 МТ К МТ РАМ I МТ ОДО) O(7’(n)log /’(«)) А" МТ О(Т\п)) O(7’(n)log Т(п)) РАМ О(Т\п)} О(Т\п)) 1.1.4. Труднорешаемые и Л/Р-полные задачи Полиномиальным алгоритмом (или алгоритмом полиномиальной временной сложно- сти) называется алгоритм, у которого временная сложность равна О(/(л)), где /(и) — некоторая полиномиальная функция. Класс Р — это класс задач распознавания свойств (т. е. задач, решениями которых могут быть либо "да", либо "нет"), для которых существуют полиномиальные алго- ритмы. Задача распознавания свойств называется труднорешаемой, если для ее решения не существует полиномиального алгоритма, т. е. если она не принадлежит классу Р. Класс NP— это класс задач распознавания свойств, которые могут быть решены за полиномиальное время на недетерминированной РАМ при логарифмическом весовом критерии.
1022 Часть III. Приложения Недетерминированная РАМ получается из РАМ добавлением команды ВЫБОР (£i, L2,..., Lr), означающей, что недетерминированы выбор и последующее выполне- ние одного из операторов £b L2,..., Lr. Большинство практически важных задач, для которых в настоящее время не известны полиномиальные алгоритмы, после переформулировки их в виде задач распознавания свойств попадают в этот класс. Задача из NP называется NP-полной, если всякая другая задача из класса NP может быть сведена к ней за полиномиальное время. Таким образом, если для некоторой АР-полной задачи существует полиномиальный алгоритм, то и любая задача из клас- са NP полиномиально разрешима, а если какая-то задача из NP труднорешаема, то и любая АР-полная задача является труднорешаемой. Теорема Кука. Задача выполнимости булевой формулы NP-полна. Задача называется NP-трудной, если всякая задача из класса NP может быть сведена к ней за полиномиальное время. Таким образом, NP-полная задача — это NP-трудная задача, принадлежащая классу NP. Для доказательства АР-полноты некоторой задачи А е NP достаточно показать, что какая-нибудь из известных АР-полных задач В может быть сведена к А. Таким образом, процесс доказательства АР-полноты задачи А может состоять из сле- дующих четырех шагов: 1. Доказательства, что Л е АР. 2. Выбора подходящей известной АР-полной задачи В. 3. Построение функции/ сводящей задачу В к задаче А. 4. Доказательство того, что функция f осуществляет полиномиальное сведение. Методы, используемые при построении указанного сведения для доказательства ре- зультатов об АР-полноте конкретных задач, меняются почти в столь же широких пределах, как и сами АР-полные задачи, и поэтому здесь у нас нет возможности про- иллюстрировать их все. Однако имеется три общих метода доказательства, которые часто встречаются и могут подсказать путь к доказательству АР-полноты новой зада- чи, которые получили названия сужение задачи, локальная замена и построение ком- поненты. Доказательство методом сужения АР-полноты фиксированной задачи А е АР за- ключается просто-напросто в установлении того, что задача А включает в качестве частного случая известную АР-полную задачу В. Суть состоит в том, чтобы указать дополнительные ограничения, которые требуется наложить на индивидуальные зада- чи из В, чтобы получившаяся в результате сужения задача была бы эквивалентна А. При этом не требуется, чтобы возникающая в результате сужения задача была точной копией известной АР-полной задачи, необходимо только, чтобы между задачами имелось "очевидное" взаимно-однозначное соответствие, сохраняющее ответы "да" или "нет". Взаимно-однозначное соответствие, которое дает сведение В к А, обычно настолько очевидно, что его даже не требуется указывать явно.
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1023 Сводимости, возникающие при доказательстве методом локальной замены, доста- точно нетривиальны, чтобы их всегда можно было с гарантией представить- в стан- дартном виде, однако они остаются относительно несложными. Этот метод состоит в том, что выбирается некоторое характерное свойство известной Л'/’-полной задачи, с помощью него образуется семейство основных модулей, а соответствующие инди- видуальные задачи заданной задачи получаются путем единообразной замены каждо- го основного модуля некоторой другой структурой. Последний и наиболее сложный метод доказательства УР-полноты — это построение компонент. Основная идея таких доказательств заключается в том, чтобы с помощью составных частей рассматриваемой задачи сконструировать некоторые "компонен- ты", соединяя которые можно "реализовать" индивидуальные задачи известной NP- полной задачи. При этом можно выделить компоненты двух основных типов. Одни из них можно рассматривать как компоненты, "делающие выбор" (например, выбираю- щие вершины, значения истинности переменных), а другие — как компоненты, "про- веряющие свойства" (например, проверяющие, что каждое ребро покрыто или что каждая дизъюнкция выполнена). В рассматриваемой индивидуальной задаче эти ком- поненты связаны так, что выбранные значения передаются компонентам, проверяю- щим условия, и последние проверяют, удовлетворяют ли сделанные выборы значений необходимым условиям. 1.2. Язык высокого уровня В основе подхода, используемого нами для представления алгоритмов и анализа их корректности и сложности, лежит специальный язык высокого уровня (ВУ-язык). Язык позволяет формулировать алгоритмы работы с графами в естественной форме, допускающей прямой анализ их корректности и сложности, а также простой перенос алгоритмов на традиционные языки программирования и ЭВМ с сохранением полу- ченных оценок сложности. Данный язык в качестве базовых содержит традиционные конструкции математики и языков программирования. Наряду с обычными для современных языков типами простых и составных данных он позволяет использовать такие более сложные струк- туры данных, как, например, деревья, графы и т. д. Для каждой базовой конструкции ВУ-языка фиксируется класс ее допустимых реализаций на РАМ. Предполагается, что ВУ-язык разрешает наряду с базовыми использовать любые необходимые конст- рукции, если очевидны или заранее зафиксированы оценки их сложности, а также те реализации этих конструкций на РАМ, которые допускают указанные оценки. Программа на языке высокого уровня (ВУ-программа) представляет собой последо- вательность глобальных описаний переменных, процедур и функций, за которой сле- дует оператор вызова основной процедуры. Все процедуры и функции могут работать с глобальными переменными и иметь локальные переменные, а также формальные параметры; при этом скалярные параметры подставляются по значению, а структур- ные — по ссылке.
1024 Часть III. Приложения 1.2.1. Структуры данных В основе системы типов ВУ-языка лежит конечное множество данных, неделимых (простых) с точки зрения имеющихся в языке операций и образующих подмножества, называемые простыми типами данных и состоящие из целых, вещественных чисел, логических и литерных данных, ссылок и меток. Другие типы данных (составные) строятся из простых типов с помощью нескольких операций, обычно называемых конструкторами типов. Рассмотрим некоторые из основных способов структурирова- ния составных данных в ВУ-языке. Векторы, записи, шкалы и массивы Наиболее простой структурой данных является вектор — последовательность равных по объему элементов, расположенных в памяти РАМ подряд. Зная адрес начального элемента вектора и размер одного его элемента, можно за фиксированное время осу- ществить доступ к любому элементу вектора по его номеру. Обобщенный вектор (или запись) состоит из разнообъемных элементов, расположен- ных подряд. Для доступа за фиксированное время к элементам записи достаточно иметь ссылку на начальный элемент и вектор смещений элементов относительно на- чального элемента. Часто в силу своего размера несколько элементов вектора (или записи) могут быть записаны в одной ячейке — так называемые упакованные векторы (или записи). Важ- ным частным случаем упакованного вектора является шкала (или битовый вектор), когда каждый элемент вектора занимает один бит. Логические (покомпонентные) операции над шкалами будем обозначать через A, V, —i и называть расширенными (элементарными) операциями РАМ. Таким образом, логическая операция над шкала- ми длины г требует г элементарных шагов РАМ и только один расширенный шаг, а доступ к произвольному элементу занимает фиксированное время как в элементар- ных, так и в расширенных шагах. Существует такое расположение элементов многомерного массива в виде вектора, которое позволяет за фиксированное время осуществить доступ к любому элементу массива по его индексам. Перечисленные структуры данных представляют собой совокупность собственно ин- формационных элементов и управляющей информации, задающей их расположения. Будем предполагать, что эта управляющая информация вынесена в специальные записи, называемые паспортами (или дескрипторами), что позволяет иметь общую программу доступа для всех объектов одного и того же типа. Строки, очереди,стеки и списки Строка — это конечная последовательность однотипных элементов. Существенным для строки является то, что доступ к ее элементам (и любая другая работа с ними) всегда осуществляется в соответствии с их упорядоченностью: он начинается с пер- вого или последнего элемента строки и продолжается переходом от текущего элемен- та к следующему в строке или предыдущему. Строками специального вида являются стеки и очереди. В этих строках доступ возможен только к начальному элементу и
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1025 означает его удаление из строки, а вставка элемента осуществляется таким образом, что добавляемый элемент становится новым начальным в случае стека или новым конечным в случае очереди. Для строк естественной отображающей структурой является список, представляющий собой совокупность записей, каждая из которых состоит из управляющей и собствен- но информационной частей. При этом в зависимости от реальных операций над стро- кой в управляющей части содержится информация об адресах предыдущего и после- дующего элементов (двусторонний список) или информация только об адресе после- дующего элемента (односторонний список), а дескриптор списка наряду со ссылкой на первый и текущий элементы списка может включать ссылку на его последний эле- мент. Такие операции над списками, как взятие первого элемента из списка А с его удалением или без удаления (обозначение Э А и Э А), добавление элемента а в список А (обозначение А *— а) и сочленение двух списков А и В (обозначение А и В), можно выполнить за ограниченное (постоянной величиной) число шагов, а операцию добав- ления элементов списка В в список А (обозначение А <= В) — за число шагов, про- порциональное длине списка. Графы и деревья Различные представления графов и деревьев описаны в гл. 1 и 2. Нетрудно заметить, что для графа с п вершинами и т дугами любое такое представление требует порядка п + т элементов памяти и позволяет за фиксированное время осуществлять доступ к любой вершине или дуге графа, выбирать первого предшественника или преемника, а также следующего предшественника или преемника (если доступ к текущему элемен- ту уже осуществлен), выбрать первую (или следующую) дугу, исходящую из данной вершины или заходящую в нее, определить начальную НЛЧАЛО(гг) или конечную КОНЕЦ(н) вершины заданной дуги и. Множества предшественников р, преемников р, дуг, заходящих ври исходящих из р, будем обозначать через ПРЕД(р), ПРЕЕМ(р), ЗАХОД(р) и ИСХОДА) соответственно. 1 Каждое из рассмотренных представлений деревьев требует порядка п элементов па- мяти, где п — число вершин дерева, и, как правило, позволяет за фиксированное вре- мя выбирать по любой вершине р ее отца (обозначение ОТЕЦ(р)), брата (обозначение БРАТ(р)) и сына (обозначение СЫН(р)), а также проверять, является ли вершина корнем, листом или внутренней вершиной. Укладки, обходы, нумерации и разметки (вершин или дуг графа) суть отображения из некоторого множества [1 : k], к > 1, где элементами этого множества являются имена вершин или дуг в случае обходов, нумераций или разметок. Поэтому для них отобра- жающей структурой является вектор. В зависимости от реальных операций над дан- ным обходом, нумерацией или разметкой (если она имеет вид отображения из [1 : Л] на множество [1 : А]) дополнительно вводится вектор, представляющий обратное ото- бражение к указанному. Наборы Пусть дано некоторое множество А. Под набором над А (построенным над множест- вом А) понимается такая структура данных, которая описывает некоторое разбиение 33 Зак 202
1026 Часть III. Приложения множества А (вначале на одноэлементные подмножества) и позволяет выполнять операции следующих двух типов: □ слить В с С, где В и С — некоторые подмножества из текущего состояния набора; результатом этой операции является замена в наборе множеств В и Сна множест- □ найти а, где а — элемент из Л; выдается имя того множества из набора, которому в данный момент принадлежит элемент а; вначале именем одноэлементного под- множества является имя элемента, образующего это подмножество. Существует такая реализация набора на РАМ, при которой любая последователь- ность, состоящая из и операций слить и не более m операций найти, может быть вы- полнена за время О(т a(m, пУ), где а(/и, и) — очень медленно растущая функция, обратная функции Аккермана. Рис. П1.3. Преобразование сжатия Эта реализация предполагает задание набора в виде помеченного графа, образованно- го совокупностью г деревьев, где г— число подмножеств в текущем состоянии набо- ра. Вершинами каждого дерева являются элементы одного подмножества, а корень дерева помечен именем этого подмножества. Считается, что операция найти а осу- ществляет следующую последовательность действий: вначале определяется вершина а в графе, затем осуществляется прохождение пути из этой вершины в корень содер- жащего ее дерева Т и определение имени множества, метящего этот корень. В про- цессе прохождения пути (аь ..., о/) от вершины а до корня осуществляется его ежа- 4 тие— такое преобразование дерева, в результате которого каждая из вершин оь..., «/-j становится сыном корня (рис. П1.3). Выполнение операции слить В с С осуществляется в следующие два этапа: сначала выбираются те два корня, которые помечены именами В и С; затем корень меньшего (по числу вершин) из двух деревьев
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1027 преобразуется в сына корня второго (большего) дерева, которому и приписывается имя С. При этом предполагается, что указанный граф представляется в памяти РАМ таким образом, что объем необходимой памяти составляет порядка | А | элементов, операция слить выполняется за фиксированное число шагов, а время выполнения операции найти а является линейным относительно длины пути от вершины а до соответст- вующего корня. Любая последовательность действий над набором, состоящая из О(п) слияний под- множеств и О(т) нахождений элементов, может быть выполнена за время O(min(n log n + т), (п + т) к a.(n, /и)). 1.2.2. Структуры действий В ВУ-языке применяются традиционные конструкции языков программирования, такие как выражения, условия, операторы и процедуры. Помимо набора операций и операторов, ориентированных на работу со структурированными данными, в ВУ- языке имеется ряд базовых конструкций, неформальное описание которых будет представлено далее. Операторы присваивания Оператор присваивания вида переменная := выражение задает присваивание переменной скалярного значения выражения или ссылки на его составное значение Таким образом, временная сложность оператора присваивания определяется как время, затрачиваемое на вычисление выражения плюс единица. Выполнение группового оператора присваивания (переменная!,..., переменная А) := (выражение!,..., выражение N) состоит из двух последовательно выполняемых шагов: вычисления значений "значе- ние 1",..., "значение А” всех выражений, стоящих в правой части, и N присваиваний, К-е из которых имеет вид "выражение К := значение К". Составной и условный операторы Составной оператор — это серия операторов, заключенных в операторные скобки начало и конец; время его выполнения равно сумме времен выполнения операторов, составляющих серию. Имеются две формы условных операторов: если условие то серия операторов иначе серия операторов все, если условие то серия операторов все. Время выполнения условного оператора складывается из времен, требуемых на про- верку условия и выполнения соответствующей серии операторов.
1028 Часть III. Приложения Операторы прерывания Любой из операторов ВУ-программы можно сделать помеченным, написав перед ним метку через двоеточие. Главное назначение метки — дать возможность оператору прерывания, имеющему одну из следующих форм: завершить метка при условие, завершить метка, начать метка при условие, начать метка, остановить текущее выполнение помеченного оператора данной меткой. При этом оператор завершить выводит за помеченный оператор, а оператор начать приводит к его новому выполнению. Если оператор прерывания содержит условие, то переход осуществляется только при истинном его значении. Сложность оператора прерыва- ния равна времени, требуемому на проверку условия плюс единица. Операторы цикла Имеются следующие виды операторов цикла: пока условие цикл серия операторов все. повторять серия операторов до условие все, цикл серия операторов все, для переменная от начальное значение до конечное значение через шаг цикл серия операторов все, для переменная от начальное значение до конечное значение цикл серия операторов все, для всех переменная из выражение цикл серия операторов все. В операторе пока при истинности условия происходит выполнение серии операто- ров, и этот процесс повторяется до тех пор, пока условие не станет ложным. Время, требуемое на его выполнение, получается суммированием времен, необходимых для всех сделанных проверок условия и всех осуществляемых выполнений серии опера- торов. Оператор повторять трактуется аналогично оператору пока, но в нем серия опера- торов выполняется до проверки условия, и истинность условия завершает выполне- ние цикла. Оператор цикл S все эквивалентен оператору пока истина цикл S все. В операторе для начальное значение, конечное значение и шаг являются выражения- ми, которые вычисляются один раз в начале выполнения оператора, а шаг, равный 1, иногда опускается. В операторе для всех сначала вычисляется выражение, значением которого является составной объект, как правило, строка. Затем выполняется серия операторов для каж- дого элемента вычисленного составного объекта, взятого в качестве значения перет
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1029 менной. Например, если А — непустая строка, не изменяемая при выполнении опера- тора S, то оператор для всех х из А цикл S' все эквивалентен оператору повторять х := Э A; S до А = 0 все, т. е. оператор В <= А эквивалентен оператору для всех а из А цикл В <— а все. Анализ сложности операторов повторять, цикл, для и для всех должен быть очеви- ден в свете предыдущего анализа оператора пока. Описание переменных Осуществляется с помощью оператора переменная : тип = выражение, в котором либо выражение, задающее начальное значение переменной, либо тип пе- ременной могут отсутствовать. Сложность оператора описания на единицу больше времени, необходимого для вычисления выражения. Следует заметить, что обычно переменные не будут описываться, если их смысл лег- ко восстанавливается из контекста. Процедуры и функции Процедурный механизм поддерживается следующими видами операторов: проц имя (список формальных параметров) = серия операторов все, проц имя = серия операторов все, функ имя (список формальных параметров) = серия операторов все, функ имя = серия операторов все, возврат выражения, вызвать имя (список фактических параметров), вызвать имя. В ВУ-программе можно определить и впоследствии вызвать процедуры и функции. После того как функция описана с помощью оператора функ, к ней можно обратить- ся в любом выражении, вызывая ее по имени с нужными фактическими параметрами. При обращении к функции последним оператором, выполняемым в данной функции, должен быть оператор возврат. Этот оператор приводит к окончанию выполнения обращения к функции и выдает в качестве его результата значение выражения, стоя- щего за словом возврат. Процедура описывается с помощью оператора проц, и к ней можно обратиться с по- мощью оператора вызвать, содержащего нужные фактические параметры. В процес- се выполнения оператора вызвать обычно изменяются объекты, глобальные по от- ношению к процедуре. В определении процедуры оператор возврат не нужен: за- вершение выполнения серии операторов, образующей тело процедуры, завершает и выполнение оператора вызвать. Слово вызвать в операторе обращения к процедуре может отсутствовать.
1030 Часть III. Приложения Время на обращение к процедуре или к функции равно времени, требуемому на вы- полнение соответствующей серии операторов плюс длина списка формальных пара- метров. 1.2.3. Дополнительные средства В ВУ-программу можно вставлять комментарии (например, в виде номеров операто- ров, начинающих строки, изображающие операторы ВУ-программы, или в виде от- дельного оператора % примечание %, имеющего нулевую сложность), а также ис- пользовать практически все, что читаемо и недвусмысленно. 1.3. Список /VP-полных задач Приведенный в данном разделе список может служить источником информации о том, какие задачи нельзя решить за полиномиальное время при условии, что Р ф NP. Он содержит более 300 задач, для которых в настоящее время их УР-иол нота или УР-трудность уже установлена. Каждый элемент списка состоит из двух частей: на- звания задачи и ее описания, имеющего, как правило, вид вопроса. Иногда описание задачи не может быть осуществлено в общеизвестных терминах и объектах, описан- ных в книге. Поэтому некоторые описания помимо вопроса содержат некоторый под- готовительный материал. При этом определения, общие для нескольких задач, приво- дятся один раз, в первой задаче, для формулировки которой они потребовались. Стремление сделать описание сжатым не всегда позволяло нам привести полную и четкую формулировку задачи. Некоторые описания задач можно рассматривать лишь как наброски формулировок, стимулирующих читателя для поиска в литературных источниках более точных описаний задач. Задачи в списке разбиты на тематические группы: покрытия и разбиения, подграфы и изоморфизм, расположения, укладки и нумерации, остовные деревья, разрезы и связ- ность, пути, сети, множества и разбиения, хранение и поиск, программы и схемы, автоматы и языки, логика, игры и головоломки, алгебра и теория чисел, математиче- ское программирование, теория расписаний и разные задачи. Многие задачи из спи- ска вполне можно отнести к разным категориям, что следует иметь в виду при поиске той или иной конкретной задачи. Некоторые дополнительные УР-полные задачи, свя- занные с расположением графа на плоскости, содержатся в приложении 2. 1.3.1. Покрытия и разбиения 1. D-морфизм ориентированных графов. Пусть заданы два орграфа Gi=(H,/l) и G2 = (Иг, Л2). D-морфизмом G] в G2 называется такая функция f.V\ —> V2, что справедливы следующие два свойства: для каждой пары (p,q)&A\, либо (Др),/<7)) g Аг, либо (/(<?), Лр))еЛ2; Для всех ре И и q'e V2, если (Др), q')^A2, то существует такая вершина х в множестве f'(qr), что (р, х) е А}. Существует ли D-морфизм графа Gt в граф G2?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1031 2. Ахроматическое число дополнения. Верно ли, что ахроматическое число задан- ного графа, являющегося дополнением к двудольному графу, не меньше заданно- го числа? 3. Ахроматическое число. Верно ли, что ахроматическое число заданного графа не меньше заданного числа? 4. Вершинное покрытие планарного графа Существует ли в заданном планарном графе, степени всех вершин которого не превосходят 4, вершинное покрытие мощности, не превосходящей заданной, которое порождает связный подграф ис- ходного графа? 5. Вершинное покрытие. Существует ли в заданном графе вершинное покрытие мощности, не превосходящей заданной? 6. Гамильтоново пополнение. Можно ли добавить в заданный граф не более чем за- данное число ребер, чтобы в полученном графе был гамильтонов цикл? 7. Гомоморфизм графов. Отождествление двух несоседних вершин р и q— это за- мена их одной вершиной, соединенной в точности с теми вершинами, с которы- ми были соединены р и q (хотя бы одна из них). Можно ли из заданного графа последовательностью отождествлений несоседних вершин получить граф, изо- морфный другому заданному графу? 8. Двудольный подграф графа степени 3. Существует ли в заданном графе, не имеющем вершин степени более 3 и не содержащем треугольников, порожден- ный двудольный подграф, содержащий не менее заданного числа вершин? 9. Двудольный подграф. Существует ли в заданном графе порожденный двудоль- ный подграф, содержащий не менее заданного числа вершин? 10. Двудольный связный подграф. Существует ли в заданном графе, не имеющем вершин степени более 3, порожденный двудольный связный подграф, содержа- щий не менее заданного числа вершин? 11. Доминирующее множество графа степени 3. Существует ли в заданном графе, степени всех вершин которого не превосходят 3, доминирующее множество, со- стоящее не более чем из заданного числа вершин? 12. Доминирующее множество планарного графа. Существует ли в заданном пла- нарном графе, степени всех вершин которого не превосходят 4, доминирующее множество, состоящее не более чем из заданного числа вершин? 13. Доминирующее множество. Существует ли в заданном графе доминирующее множество, состоящее не более чем из заданного числа вершин? 14. Максимальное паросочетание подграфов. Заданы два орграфа Gi=(H, £j), G2= (Сг, £2) и положительное целое число к. Существует ли такое подмножество Лс И, х что | £ | > к и для всех {р, р’), {q,q}^R дуга (р, q) принадлежит А । тогда и только тогда, когда (Д', q') е Л2? 15. Множество вершин, разрезающих контуры орграфа степени 2. Существует ли в заданном орграфе, все вершины которого имеют степени захода (или выхода)
1032 Часть III Приложения не более 2, множество вершин, разрезающее контуры, состоящее не более чем из заданного числа вершин? 16. Множество вершин, разрезающих контуры планарного графа. Существует ли в заданном планарном орграфе, все вершины которого имеют степени захода (или исхода) не более 3, множество вершин, разрезающее контуры, состоящее не бо- лее чем из заданного числа вершин? 17. Множество вершин, разрезающих контуры. Существует ли в заданном орграфе множество вершин, разрезающее контуры, состоящее не более чем из заданного числа вершин? 18. Множество дуг, разрезающих контуры орграфа степени 3. Существует ли в за- данном орграфе, все вершины которого имеют степени захода и исхода не бо- лее 3, такое подмножество дуг мощности, не превосходящей заданной, которое содержит по крайней мере одну дугу из каждого контура орграфа? 19. Множество дуг, разрезающих контуры. Существует ли в заданном орграфе такое подмножество дуг мощности, не превосходящей заданной, которое содержит по крайней мере одну дугу из каждого контура орграфа? 20. Множество дуг, частично разрезающих циклы. Существует ли в заданном графе такое подмножество, состоящее не более чем из заданного числа дуг, которое со- держит по крайней мере одну дугу из каждого контура, имеющего длину не ме- нее заданной? 1.3.2. Подграфы и изоморфизм 1. Изоморфизм подграфу. Есть ли в заданном графе такой порожденный подграф, который изоморфен другому заданному графу? 2. Клика. Верно ли, что заданный граф содержит клику не менее заданного размера? 3. Кубический подграф Существует ли в заданном графе G = (K, Е) такое подмно- жество ребер £', что в графе G = (V, Е') любая вершина имеет степень, равную 3 или 0? 4. Минимальное по мощности максимальное паросочетание двудольного графа. Су- ществует ли в заданном двудольном графе, не имеющем вершин, степени выше 3, максимальное паросочетание, состоящее не более чем из заданного числа вершин? 5. Минимальное по мощности максимальное паросочетание планарного графа. Су- ществует ли в заданном планарном графе максимальное паросочетание, состоящее не более чем из заданного числа вершин? 6. Минимальное по мощности максимальное паросочетание. Существует ли в задан- ном графе максимальное паросочетание, состоящее не более чем из заданного числа вершин? 7. Минимальный А-связный подграф. Существует ли в заданном графе G=(E,E) такое подмножество ребер Е' мощности не более заданной, что граф G' = (K, Е') является /с-связным, где к — заданное положительное целое число?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1033 8. Минимальный эквивалентный орграф. Существует ли в заданном орграфе G = (£, А) такое подмножество дуг А' мощности, не превышающей заданного числа, что для любой пары вершин р, q е К, в графе G' = (V, А1) есть путь от р до q тогда и только тогда, когда есть путь отр к q в G? 9. Монохроматический треугольник. Существует ли разбиение множества Е задан- ного графа G = (К, Е) на два непересекающихся подмножества £, и £2 такие, что ни один из графов Gt = (И, £,) или G2 = (К, Е2) не содержит треугольника? 10. Наиболее общий подграф. Существуют ли в двух заданных графах G] = (К,, Е}) и G2 = (V2, Е2) такие подмножества £fc £, и £2'с Е2, что \Е( |=|| > к, где к — задан- ное положительное целое число, и графы (Кь £,') и (у2, Е2) изоморфны? 11. Независимое множество (или пустой подграф). Верно ли, что заданный граф со- держит пустой порожденный подграф не менее заданного размера? 12. Независимое множество двудольного графа. Верно ли, что заданный двудольный граф содержит пустой порожденный подграф не менее заданного размера? 13. Независимое множество планарного графа. Верно ли, что заданный планарный кубический граф содержит пустой порожденный подграф не менее заданного раз- мера? 14. Односторонне связный подграф. Существует ли в заданном орграфе G = (И, А) такое подмножество дуг мощности А' не менее заданной, что в графе G'= (К, А') между любой парой вершин есть по крайней мере один ориентированный путь? 15. Планарная часть графа. Существует ли в заданном графе планарная часть, содер- жащая не менее заданного числа ребер? 16. Планарный подграф. Существует ли в заданном графе порожденный планарный подграф, содержащий не менее заданного числа вершин? 17. Покрытие кликами. Существует ли в заданном графе не более чем заданное чис- ло полных подграфов, содержащих все ребра графа? 18. Покрытие полными двудольными подграфами. Существует ли в заданном дву- дольном графе не более чем заданное число полных двудольных подграфов, со- держащих все ребра графа? 19. Пополнение до графа интервалов. Можно ли добавить в заданный граф не более чем заданное число ребер, чтобы полученный граф стал графом интервалов? 20. Пополнение до графа путей. Можно ли добавить в заданный граф не более чем заданное число ребер, чтобы полученный граф стал графом пересечения семей- ства путей в некотором неориентированном дереве? 21. Порожденный подграф с наследуемым свойством. Пусть Р обозначает любое та- кое свойство графов, которое выполняется для произвольно больших, но не всех графов и обладает свойством "наследственности", т. е. свойство выполняется для всех подграфов графа, если оно выполняется для самого графа. Примеры таких свойств: граф есть клика, граф является пустым, граф является планарным, граф является двудольным, граф является внешнепланарным, граф является реберным,
1034 Часть III. Приложения граф является триангулированным, граф есть граф сравнимости, граф есть лес. Существует ли в заданном графе порожденный подграф, который обладает свой- ством Р и содержит не менее заданного числа вершин? 22. Порожденный путь. Существует ли в заданном графе порожденный подграф, ко- торый является простым путем заданной длины? 23. Порожденный путь двудольного графа. Существует ли в заданном двудольном графе порожденный подграф, который является простым путем заданной длины? 24. Порожденный связный подграф с наследуемым свойством. Пусть Р обозначает любое свойство, перечисленное в предыдущей задаче, кроме "граф является пус- тым". Существует ли в заданном графе порожденный связный подграф, который обладает свойством Р и содержит не менее заданного числа вершин? 25. Порожденный цикл. Существует ли в заданном графе порожденный подграф, ко- торый является простым циклом заданной длины? 26. Разбиение на гамильтоновы подграфы. Можно ли разбить вершины заданного графа на попарно непересекающие подмножества, каждое из которых состоит не менее чем из трех вершин и порождает подграф, содержащий гамильтонов цикл? 27. Разбиение на два паросочетания. Можно ли разбить вершины заданного графа на два непересекающихся подмножества, каждое из которых порождает подграф, который является совершенным паросочетанием (или состоит из вершин степе- ни 1)? 28. Разбиение на изоморфные подграфы. Верно ли, что вершины заданного графа G можно разбить на заданное число попарно непересекающихся подмножеств, каждое из которых порождает подграф, изоморфный заданному графу /7? 29. Разбиение на клики. Существует ли в заданном графе не менее чем заданное чис- ло попарно непересекающихся полных подграфов, содержащих все вершины гра- фа? 30. Разбиение на леса. Можно ли разбить вершины заданного графа не менее чем на заданное число попарно непересекающихся подмножеств, каждое из которых по- рождает подграф, являющийся лесом? 31. Разбиение на подграфы, изоморфные фиксированному графу. Фиксирован граф Н, содержащий не менее 3 вершин. Верно ли, что вершины заданного графа G можно разбить на заданное число попарно непересекающихся подмножеств, каждое из которых порождает подграф, изоморфный Н? 32. Разбиение на пути длины 2. Существует ли в заданном графе с кратным 3 числом вершин множество попарно непересекающихся путей длины 2, содержащих все вершины графа? 33. Разбиение на совершенные паросочетания. Можно ли разбить вершины заданно- го графа не менее чем на заданное число попарно непересекающихся подмно- жеств, каждое из которых порождает подграф, который является совершенным паросочетанием или состоит из вершин степени 1 ?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1035 34. Разбиение на совершенные паросочетания планарных графов. Можно ли разбить вершины заданного планарного кубического графа не менее чем на заданное чис- ло попарно непересекающихся подмножеств, каждое из которых порождает подграф, который является совершенным паросочетанием (или состоит из вер- шин степени 1)? 35. Разбиение на треугольники. Существует ли в заданном графе с кратным 3 числом вершин множество попарно непересекающихся треугольников, содержащих все вершины графа? 36. Раскрашиваемость графа (хроматическое число). Верно ли, что заданный граф является ^-раскрашиваемым, где А: — заданное положительное целое число? 37. Раскрашиваемость графа в три цвета. Верно ли, что заданный граф является 3-раскрашиваемым? 38. Раскрашиваемость планарного графа. Верно ли, что заданный планарный граф, степени всех вершин которого не превосходят 4, является A-раскрашиваемым, где к—заданное положительное целое число? 39. Реберный подграф. Существует ли в заданном графе порожденный подграф, со- держащий не менее заданного числа вершин и являющийся реберным для неко- торого графа? 40. Реберный подграф графа степени 3. Существует ли в заданном графе, не имею- щем вершин степени большей 3, порожденный связный подграф, содержащий не менее заданного числа вершин и являющийся реберным для некоторого графа? 41. Реберный подграф графа степени 4. Существует ли в заданном графе, не имею- щем вершин степени большей 4, порожденный подграф, содержащий не менее заданного числа вершин и являющийся реберным для некоторого графа? 42. Сбалансированный полный двудольный подграф. Существует ли в заданном дву- дольном графе G = (Ph И2, Е) два подмножества И'с И и И2'с И2, такие, что |И1= Ml = к и подграф, порожденный множеством V{<j И2, является полным дву- дольным? 43. Связный подграф ограниченной степени. Существует ли в заданном графе поро- жденный связный подграф, состоящий из не менее заданного числа вершин, ко- торый не содержит вершин, имеющих степень более заданной? 44. Стягиваемость графа. Под стягиванием ребра будем понимать такое преобразо- вание графа, при котором две соседние вершины р и q заменяются одной новой вершиной, соединенной ребрами с теми и только теми вершинами, с которыми были соединены р или q. Можно ли из заданного графа последовательностью стягиваний ребер получить граф, который изоморфен другому заданному графу? 45. Транзитивный подграф. Существует ли в заданном орграфе G = (И, А) такое под- множество дуг А' мощности не менее заданной, что орграф & = (¥, А1) является транзитивным? 46. Число доминирующих множеств. Верно ли, что можно разбить множество вер- шин заданного графа на заданное число попарно непересекающихся подмно- жеств, каждое из которых является доминирующим множеством?
1036 Часть III. Приложения 1.3.3. Расположения, укладки и нумерации 1. К-замыкание. Существует ли в заданном орграфе G = (Г, А) такое подмножество вершин И', мощности не превышающей заданного числа К, что для любой дуги (р, q) е А либо р е W, либо q <£ V"? 2. Базис графа пересечений. Верно ли, что заданный граф является графом пересе- чений семейства множеств, объединение которых имеет мощность не более за- данной? 3. Взвешенный диаметр. Заданы граф G = (V, Е), набор С, состоящий из |£| неотри- цательных целых чисел (не обязательно различных), и положительное целое чис- ло к. Существует ли такая биекция/: £ —> С, что при интерпретации Де) как дли- ны ребра е диаметр графа G не превосходит к? 4. Гамильтонов путь. Верно ли, что в заданном графе есть гамильтонов путь? 5. Гамильтонов путь двудольного графа. Есть ли в заданном двудольном графе гамильтонов путь? 6. Гамильтонов путь орграфа. Верно ли, что в заданном орграфе есть гамильтонов путь? 7. Гамильтонов путь планарного графа. Есть ли в заданном планарном, кубическом 3-связном графе гамильтонов путь? 8. Гамильтонов цикл. Есть ли в заданном графе гамильтонов цикл? 9. Гамильтонов цикл двудольного графа. Есть ли в заданном двудольном графе гамильтонов цикл? 10. Гамильтонов цикл квадрата. Есть ли в квадрате заданного графа гамильтонов цикл? И. Гамильтонов цикл планарного графа. Есть ли в заданном планарном, кубическом 3-связном графе, не имеющем граней, ограниченных меньше чем пятью ребрами, гамильтонов цикл? 12. Гамильтонов цикл реберного графа. Есть ли в заданном реберном графе гамиль- тонов цикл? 13. Линейное упорядочение с минимальным разрезом. Существует ли такая нуме- рация F заданного графа G = (Г, £), что для всех i мощность множества {{р, q}eE: F(p) </< F(cj)} не превышает заданного положительного целого числа? 14. Метрическая размерность. Заданы граф G = (F Е) и положительное целое число к <|Г]. Подмножество Г'с Г называется базисом метрик G, если для каждой пары вершин p,q е V существует такая w е Г', что различны длины кратчайших путей от р к w и от q к w. Есть ли у графа G базис метрик мощности, не превышаю- щей А? 15. Множество дуг, различающее пути. Заданы орграф G = (V,A) с двумя выделен- ными вершинами р0 и q0 и положительное целое число к. Существует ли такое
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1037 подмножество А'с, А, что |Л'|< к и для каждой пары путей Р] и Р2 из р0 в q0 най- дется дуга в А', принадлежащая ровно одному из них? 16. Нумерация графа по Грунди. Для заданного орграфа G = (И, А) существует ли та- кая функция /: У —> FT, что любой вершины р g V значение Др) равно наимень- шему неотрицательному числу, не содержащемуся в множестве {f(q): q е V, (p,q) g А}? 17. Оптимальное линейное упорядочение графа. Существует ли такая нумерация F заданного графа G = (У, Е), что | F(q)- F(p)\<k, где к — заданное поло- '/} еЛ жительное целое число? 18. Оптимальное линейное упорядочение двудольного графа. Существует ли такая нумерация Fзаданного двудольного графа G = (И, £), что £|£(<7)-F(p)|<£, {р,Ч}еА где к — заданное положительное целое число? 19. Оптимальное линейное упорядочение орграфа. Существует ли такая нумерация F заданного орграфа G = (V, А), что любая дуга (р. q) е А является F-дугой и £(£(<?)-£(/,))< к , где к — заданное положительное целое число? (р.чУА 20. Ориентированный гамильтонов цикл. Есть ли в заданном орграфе гамильтонов цикл? 21. Ориентированный гамильтонов цикл планарного графа. Есть ли в заданном пла- нарном орграфе, не имеющим вершин, инцидентных более чем трем дугам, га- мильтонов цикл? 22. Ориентированный диаметр. Можно ли так ориентировать ребра заданного графа, что возникший в результате орграф является сильно связным и имеет диаметр не более заданного? 23. Паросочетание со многими вариантами. Заданы граф G = (V, Е), разбиение его ребер на попарно непересекающиеся подмножества Е}, Е2,..., £.? и положитель- ное целое число к. Существует ли подмножество Е'с_Е такое, что |£7'| > к, ника- кие два ребра из Е' не являются смежными и для всех i, 1 < i<s, пусто пересече- ние Е' г\ Е,? 24. Последовательное исключение степеней. Заданы граф G = (V,E) и последова- тельность d], d2,..., d^ неотрицательных целых чисел, не превышающих |Е]-1. Существует ли такая нумерация F вершин графа G, что для всех /, 1 < i < |И] су- ществует в точности d, вершин в множестве {р : F(p) >i и {p,F~'(i)}eE}r? 25. Представление в виде корневого дерева. Заданы граф G = (У, Е) и положительное число к. Существуют ли корневое дерево Т — (U, F), где |t?|=|E], и биекция ft У —> U, такие, что для любого ребра {р, q)&E найдется простой путь, на- чинающийся в корне и проходящий через ftp) и fq), для которого ^d(f(p),f(q})< к, где d(x, у) — число ребер на пути от х до у в дереве П {р,ч}^1-
1038 Часть III. Приложения 26. Путь с запрещенными парами. Заданы орграф G = (K, А), набор С = {(pi,qt),..., (р„, qn~)} пар вершин из V и две выделенные вершины .v, t, е V. Существует ли в G путь от 5 к t, содержащий не более одной вершины из каждой пары набора С? 27. Размерность Нешетрил-Редл. Существует ли для заданного графа G = (И, Е) такая биекция/: V —> {(аь ..., о*): 1 < а, < |К] при 1 < i < к}, где к — заданное положи- тельное целое число, что пара вершин р, q е V соединены ребром {р, q} е Е то- гда и только тогда, когда Др) uf(q) различны по всем к координатам. 28. Упорядоченное исключение для орграфа. Существует ли для заданного орграфа G = (У, А) такая нумерация его вершин F, что имеется не более чем заданное чис- ло пар вершин (р, q) е И2\ А, обладающих свойством: G содержит путь из р в q, проходящий только через такие вершины м>, что F(w) < min{F(p), F(<y)}? 29. Ширина. Существует ли такая нумерация F заданного графа, что для всех его ре- бер {р, q} выполнено соотношение |F(p) - F(q)\ < к, где к — заданное положи- тельное число? 30. Ширина дерева. Существует ли такая нумерация F заданного дерева со степенью вершин, не превышающей 3, что для всех его ребер {р, q} выполнено соотноше- ние \F(p) - F(q)\ < к, где к — заданное положительное число? 31. Ширина корневого ордерева. Существует ли такая нумерация F заданного кор- невого двоичного ордерева, что любая его дуга (р, q) является F-дугой и F(g) — F(p) < к, где к — заданное положительное целое число? 32. Ширина орграфа. Существует ли такая нумерация F заданного орграфа, что лю- бая его дуга (р, q) является F-дугой и F(q) - F(p) < к, где заданное положи- тельное целое число? 33. Ядро. Существует ли ядро в заданном орграфе? 1.3.4. Остовные деревья 1. К наилучших остова. Заданы граф G = (И, Е), веса w(e) е No его ребер ееЕ, поло- жительные целые числа К и В. Существует ли в G ровно К различных остовов, общий вес которых не превосходит В? 2. Ветвление со многими вариантами. Заданы орграф G = (У, А), веса w(e) е ВТ его дуг a g А, разбиение А на попарно непересекающиеся подмножества А\,As и положительное целое число К. Верно ли, что есть такое подмножество А ' с. А, что ^w(a)>K, А' не содержит циклов и в А' нет двух дуг, заходящих в одну и ту же аеА' вершину или принадлежащих одному и тому же множеству А,1 3. Ветвление со многими вариантами в сильно связном графе. Заданы сильно связ- ный орграф G = (К, А), разбиение А на попарно непересекающиеся подмножества А\,..., As и положительное целое число К. Верно ли, что есть такое подмножество А’с^А, что : а е А'}| >К, А' не содержит циклов и в Л' нет двух дуг, заходящих в одну и ту же вершину или принадлежащих одному и тому же множеству Ар
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1039 4. Геометрический остов с ограниченной пропускной способностью. Заданы мно- жество Р с N х Д' точек плоскости, выделенная точкаро^Р, потребность r(p) еЛ^ для каждой реР\{/?0}, пропускная способность сеМ и граница B&N'. Существует ли в полном графе G = (Р, Е) такой остов Т = (Р, Ечто d(e) < В, где ее/:’ d((xx,У] )(х2,у2 ) = ((Х] + х2)2 + (У] - у2)2 — дискретное евклидово расстоя- ние, причем < с для каждого ребра е е Е’, где (7(e)— множество всех ре(7(е) таких вершин р, что путь в дереве Т, соединяющий р с р0, содержит ребро е? 5. Геометрическое дерево Штейнера. Задано конечное множество точек Р на плос- кости. Есть ли такое конечное множество точек Q той же плоскости, что сущест- вует остов полного графа с вершинами Р о Q и ребрами, которые являются от- резками прямых, соединяющих соответствующие точки, и имеют веса, равные длинам отрезков, общий вес ребер которого не превышает заданного положи- тельного числа К? 6. Дерево Штейнера на графе. Заданы граф G = (E, £), веса w(e) е До его ребер ее Е, подмножество вершин И'с Ии положительное целое число К. Существует ли в G такое поддерево, содержащее все вершины из W, общий вес ребер которо- го не превосходит К? 7. Дерево Штейнера на двудольном графе. Заданы двудольный граф G - (У, Е), веса w(e) е No его ребер е е Е, такое подмножество вершин W cz V, что нет ребер ме- жду вершинами из fV и Е\ W, и положительное целое число К. Существует ли в G такое поддерево, содержащее все вершины из W, общий вес ребер которого не превосходит К? 8. Дерево Штейнера на планарном графе. Заданы планарный граф G = (E, £), веса w(e) е Nq его ребер е е Е, подмножество вершин W с V и положительное целое число К. Существует ли в G такое поддерево, содержащее все вершины из W, общий вес ребер которого не превосходит КР 9. Изоморфный 3-звезде остов. Верно ли, что заданный граф содержит остов, изо- морфный заданной 3-звезде? 10. Изоморфный дереву остов. Верно ли, что заданный граф содержит остов, изо- морфный заданному дереву? 11. Изоморфный полному бинарному дереву остов. Верно ли, что заданный граф со- держит остов, изоморфный заданному полному бинарному дереву? 12. Изоморфный пути остов. Верно ли, что заданный граф содержит остов, изо- морфный заданному пути? 13. Лес с ограниченными по весу компонентами. Заданы граф G = (V,E) веса w(e) е No его вершин р положительные целые числа К и В. Существует ли разбиение вершин V на такие попарно непересекающиеся подмножества
1040 Часть III. Приложения V\, И2,Vk, где к<К, что для любого i подграф, порожденный множеством является деревом и сумма весов всех вершин из V, не превосходит В? 14. Лес с ограниченными по числу вершин компонентами. Заданы граф G = (У, Е) целые числа К> 0 и В > 2. Существует ли разбиение вершин V на такие попарно непересекающиеся подмножества И2,Vk, где к<К, что для любого i | V, | < В и подграф порожденный множеством V» является деревом? 15. Оптимальный коммуникационный остов. Заданы полный граф G = (V, Е), веса и<(е) g Лд всех его ребер е g Е, потребность r{{p, q}) g Л'(', для каждой пары {р, q} вершин из V, граница В е До- Существует ли в G такой остов Т, что £w({Ag}).r({A9})<£, где w({p, q})— сумма весов ребер пути в остове Т, соединяющего р с <?? 16. Остов ограниченного диаметра. Заданы граф G-(V,E), веса w(e) е М ребер е ё Е, а также положительные числа W и D < |Р]. Существует ли в графе G такой остов Т, что сумма весов ребер остова Т не превосходит IV и в остове Т нет про- стого пути, число ребер которого превосходит £>? 17. Остов ограниченного диаметра графа с двумя весами ребер. Заданы граф G=(C, £), веса и(е) g {1,2} ребер в е Е, а также положительные числа IV и D < |И]. Существует ли в графе G такой остов Т, что сумма весов ребер остова Т не превосходит IV и в остове Т нет простого пути, число ребер которого превос- ходит £>? 18. Остов ограниченной степени. Существует ли в заданном графе остов, у которого степени всех вершин не превосходят заданной? 19. Остов планарного графа (с максимальным числом висячих вершин) Существует ли в заданном планарном графе, степени вершин которого не превосходят 4, ос- тов, у которого не менее заданного числа вершин степени 1? 20. Остов регулярного графа (с максимальным числом висячих вершин) Существует ли в заданном регулярном графе степени 4 остов, у которого не менее заданного числа вершин степени 1? 21. Остов с кратчайшим полным путем. Существует ли такой остов Т заданного гра- фа G, что для любых пар вершин р, q графа G сумма длин путей от р до q в осто- ве Т не превосходит заданной? 22. Остов с максимальным числом висячих вершин. Существует ли в заданном графе остов, у которого не менее заданного числа вершин степени 1? 23. Остов с ограниченной пропускной способностью. Заданы граф G = (V, Е) с выде- ленной вершиной рое V, пропускные способности c(e)e7V+ и длины /(е) е л£ всех ребер е е £, потребность r(p) g /Vq для каждой вершины ре И\{р0} и число В g Л^. Существует ли в G такой остов Т, что сумма длин его ребер не превосхо- дит В и для каждого ребра е в Т выполняется соотношение ^/(р) < с(е), где Де1/(е)
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1041 U(e) — множество вершин, для которых путь в Т, соединяющий эту вершину с р0, содержит ребро е? 24. Остов с ограниченной пропускной способностью для сетей с фиксированными способностями и потребностями. Заданы граф G — (V, Е) с выделенной вершиной Ро e V, длины /(е) с < всех ребер е е Е и число В g No- Существует ли в G такой остов Т, что сумма длин его ребер не превосходит В и для каждого ребра е в Т выполняется соотношение \{р : р е С7(е)}| < 3, где U(e) — множество вершин, для которых путь в Т, соединяющий эту вершину с р0, содержит ребро е? 1.3.5. Разрезы и связность I. Ациклическое разбиение на ограниченные части. Задан орграф G = (V,A) и по- ложительные целые числа IV и К. Существует ли такое разбиение вершин графа на попарно непересекающиеся подмножества К2,..., Vs, что справедливы сле- дующие три свойства: орграф G'=(Y',Ar) является ациклическим, где К'= {Izh И2,..., Vs} и (К, е А') тогда и только тогда, когда (р„ р,)еА для некото- рых р,е V, и pj е V}; число вершин каждого из множеств Г, не превосходит IV; чис- ло всех дуг графа G, имеющих концы в разных множествах разбиения, не превос- ходит К? 2. Выживаемость сети. Заданы граф G = (И, Е), вероятности неисправности р(х) эле- ментов графа хе V(jE, 0<р(х)< 1, и вещественное число q из отрезка [0, 1]. Верно ли, что вероятность того, что для всех {w, v}g£ по крайней мере один эле- мент w, v или {u, v} неисправен, не меньше с/? 3. Двусвязное пополнение. Заданы граф G = (V,E), веса w(w) g V каждой неупоря- доченной пары {/?, q} вершин из И и положительное целое число W. Существует ли такое множество Е' неупорядоченных пар вершин из V, что У гг(г/) < РК и we// граф G'= (V, Е cj Е') является двусвязным? 4. Максимальный разрез однородной сети. Существует ли разбиение вершин задан- ного графа на два таких непересекающихся подмножества, что число ребер графа, соединяющих вершины из этих множеств, не менее заданного положи тельного це- лого числа К? 5. Минимальный разрез с ограничениями. Заданы граф G = (V,E) с двумя выделен- ными вершинами р0, q0& V, веса w(w) g М ребер и g Е, а также положительные це- лые числа К и W. Существует ли разбиение множества вершин V на два таких не- пересекающихся подмножества V\ и V2, что р0 g Vh q0 е V2, |И| < К, |И2| < К и сум- ма весов всех ребер из Е, соединяющих вершины из разных множеств V\ и И2, не превосходит W? 6. Надежность сети. Заданы граф G = (V, Е), подмножество вершин Vс V, вероятно- сти неисправности p(ii) ребер и g Е, 0 < р(и) < 1, и некоторое вещественное число q из отрезка [0,1]. Верно ли, что с вероятностью, не меньшей q, любые две верши- ны из Г'соединены по крайней мере одним путем, не содержащим неисправных ребер? 34 Зак 202
1042 Часть III. Приложения 7. Разбиение графа. Заданы граф G = (I7, А), веса w(p) е АЛ его вершинр g V, длины l(ii) его ребер и g А, а также положительные целые числа К и L. Существует ли такое разбиение вершин графа на попарно непересекающиеся подмножества Ci, V2, ..., Кч, что справедливы следующие два свойства: ^ м'(р) < £ для всех реЦ /, 1 <i<s- ^l(u)<L , где Е' с Е— множество ребер, соединяющих вершины из иеЕ' разных множеств Г)? 8. Разбиение графа на ограниченные части. Заданы граф G = (V,A), длины /(w) его ребер u g А, а также положительные целые числа КиЬ. Существует ли такое раз- биение вершин графа на попарно непересекающиеся подмножества И2,.... К?, каждое из которых содержит не более К вершин, что ^/(м) < L , где Е'с, Е— uei;' множество ребер, соединяющих вершины из разных множеств К,? 9. Реберно-связное пополнение. Заданы граф G = (V, Е), веса w(p, q) g N‘ каждой упорядоченной пары (р, q) вершин из И и положительное целое число W. Суще- ствует ли такое множество £'упорядоченных пар вершин из V, что < W ueE' и граф G' = (К, Е cj Ег) является реберно-связным (т. е. распадается после удале- ния одного ребра)? 10. Сильно связное пополнение. Заданы орграф G = (Г, А), веса w(p, </) g М каждой упорядоченной пары (р, q) вершин из Г и положительное целое число IV. Суще- ствует ли такое множество Л' упорядоченных пар вершин из V, что w(ii) < W и граф = и Л') является сильно связным? 1.3.6. Пути 1. К кратчайших путей. Заданы графы G = (V,E) с двумя выделенными вершинами р0, q0 g V, длины 1{ё) е М всех ребер е g Е и положительные целые числа L и К. Существует ли в G не менее К различных путей от р0 до д0, веса которых не пре- восходят L1 2. Геометрическая задача коммивояжера. Заданы множество PcNxN точек на плоскости и положительное целое число D. Существует ли решение задачи ком- мивояжера, в которой С = Р и cf((x1,y1),(x2,y2)) = ((Ai -х2) +(У1 — расстояние между точками? 3. Задача коммивояжера. Заданы множество С городов с расстояниями d(c„ cj) g /V* между всеми парами городов с„ c, g С и положительное целое число D. Существу- ет ли замкнутый маршрут длины не более D обхода городов с посещением каждо- го города ровно один раз?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1043 4. Задача коммивояжера для двух расстояний. Заданы множество С городов с рас- стояниями d(ch с,) 6 {1, 2} между всеми парами городов с„ с, е С и положитель- ное целое число D. Существует ли замкнутый маршрут длины не более D обхода городов с посещением каждого города ровно один раз? 5. Задача коммивояжера с ограниченными расстояниями. Заданы множество С го- родов с расстояниями d(c,, с,) 6 между всеми парами городов с,, С/ е С и по- ложительное целое число D. Существует ли замкнутый маршрут обхода городов, при котором посещается каждый город ровно один раз и расстояние между со- седними городами не превышает £>? 6. Задача о подъемном кране. Задан смешанный граф G = (V,A, Е), длины 1(e) е всех элементов е е А о Е и число L е М. Существует ли в графе G такой цикл длины не более L, который проходит по всем дугам е е А, причем, в соответст- вии с их направлением? 7. Китайский почтальон для смешанных графов. Заданы смешанный граф G = (V, А, Е), 1(e) 6 ребер е е А и дуг е е Е графа G и число D е N*. Существу- ет ли в G цикл длины не более D, содержащий все ребра и дуги графа, причем ду- ги должны входить в цикл с правильной ориентацией? 8. Кратчайший путь в графе с ограничением по весу. Заданы граф G = (V, Е) с двумя выделенными вершинами р0, q0 е V, длины 1(e) е М и веса w(e) е всех ребер е е Е и положительные целые числа L и W. Существует ли в G простой путь из р0 в q0, имеющий вес не более W и длину не более L1 9. Кратчайший путь в орграфе с ограничением по весу. Заданы орграф G = (V, А) с двумя выделенными вершинамир0, q0 е V, длины 1(e) е М и веса w(e) е М всех ребер аеА и положительные целые числа L и IV. Существует ли в G простой путь из ро в q0, имеющий вес не более IV и длину не более Z? 10. Самый длинный путь. Заданы граф G = (К, Е), выделенные вершины р0, qo и по- ложительное целое число L. Существует ли в графе G простой путь от р0 до q0 длины, не меньшей L1 11. Самый длинный путь во взвешенном графе. Заданы граф G = (V, Е) длины 1(e) 6 No всех его ребер е е Е, выделенные вершины р0, qo и положительное це- лое число L. Существует ли в графе G простой путь от р0 до qo длины, не мень- шей L? ' 12. Самый длинный цикл. Есть ли в заданном графе цикл длины не менее заданной? 13. Самый длинный цикл во взвешенном графе. Задан граф G = (V,E), длины 1(e) е всех его ребер е е Е, положительное целое число L. Есть ли в G цикл длины не менее L1 14. Сельский почтальон. Заданы граф G = (V,E), длины 1(ё) е всех его ребер е е Е, подмножество Е' с Е и число L е Л^. Есть ли в G цикл, включающий все ребра из Е и имеющий длину не более Z?
1044 Часть III. Приложения 15. Сельский почтальон в однородной сети. Заданы граф G=(E, Е), подмножество Е' cz Е и число L е Л^. Есть ли в G цикл, состоящий из не более L ребер, но вклю- чающий все ребра из Е? 1.3.7. Сети 1. Вложение ребер в решетку. Заданы граф G = (V,E) и положительные m и п. Су- ществует ли такое взаимно-однозначное отображение /: К—> {1,2,...,/и} х х {1,2,..., п}, что если {р, q} g Е, f(p) = (xb _Pi), и fig) = (х2,у2), то либо х, = х2, либо у [ =У2? 2. Граф пересечений отрезков решетки. Заданы граф G = (К, Е) и положительные це- лые числа т, п. Верно ли, что существует такое взаимно-однозначное соответст- вие f между V и множеством прямолинейных отрезков на плоскости с концами (х, у) и (z, и), где 1 < х < z < т, 1 <у < w < п и либо х = z, либо у = w, что {w, v} g Е тогда и только тогда, когда отрезкиДп) и fly) пересекаются? 3. Квадратичная задача о назначении. Заданы неотрицательные целочисленные стоимости Су,1< i,j < и, расстояния lks, 1 < s, к < т и целое положительное число к. Существует ли такое однозначное отображение f: {1,2,..., л}->{1,2,..., т}, что п п X X^.r^/wc/) -к 7 <=1 7=1 4. Максимальное число непересекающихся путей фиксированной длины. Заданы граф G= (К, Е) с двумя выделенными вершинами р0 и д0, а также положительные целые числа к и т. Верно ли, что в G содержится не менее т путей из р0 в q0, по- парно непересекающихся и содержащих ровно к ребер? 5. Максимальное число ограниченных непересекающихся путей. Заданы граф G = (К, Е) с двумя выделенными вершинами р0 и q0, а также к, т g N^, к, т < |Е]. Верно ли, что в графе G есть не менее т попарно непересекающихся путей из ро в q0, включающих не более к ребер? 6. Минимизация числа фиктивных работ. Заданы дэг заданий G = (1ZJ) и по- ложительное целое число к. Существует ли такой дэг G'=(l/I, А'), что V = = {/>,”,/л ' Р: {(Pl, Pi) '-Pi е И £ А', |Л'| < |Л| + к и в G' существует путь от р; к р] тогда и только тогда, когда в G существует путь от р, к р,1 7. Неориентированный поток, ограниченный снизу. Заданы граф G = (V,E) с двумя выделенными вершинами р0 и q0, пропускные способности с(е) g и ниж- ние границы 1(e) g Гу всех ребер е g Е, а также потребность R g М. Сущест- вует ли такая потоковая функция f: {(р, q), (q, р) : {р, q} g £} —> что выполня- ются следующие три свойства: для любого {р, q} g Е либо f((p, д)) = О, либо f((g, р)) = 0; 1(e) < max{/((p, д)), fl(q, р)) < с(е) для всех е = {р, q} g Е; X /((л%))-
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1045 8. Непересекающиеся соединяющие пути. Заданы граф G = (K,£) и набор пар вер- шин (/?ь q\),(p2, Qi), (Pk, Як), гдеPi^PjU qt* q, при i j. Верно ли, что в графе G есть к путей, попарно непересекающихся и соединяющих р, с q, для всех Z? 9. Поток в сети с ограничениями. Заданы орграф G = (V,A) с двумя выделенными вершинами р0 и q0, пропускные способности с(е) g TV* всех дуг е g А, набор Р ориентированных путей по G и потребность R. Существует ли такая функция g: Р -> Т\£, что если ft А —> Т\£ потоковая функция, определяемая соотношениями f(e) = X g(r)где Р(е) — множество всех путей из Р, содержащих дугу е, то/ ге/’(е) удовлетворяет следующим трем условиям: /е) < с(е) для всех дуг е g А\ X f^P' Я))~ X №, *)) = 0 для всех q е Л\{р0, q0}', (p,q)eA (q,')EA X f«P’V))- {p,q„)eA {q0,q)EA 10. Поток минимальной реберной стоимости. Заданы орграф G = (К, А) с двумя вы- деленными вершинами р0 и q0, пропускные способности с(е) g /V* и стоимости У(е) g Л/ всех дуг ееА, потребность R g TV* и число к g л£. Существует ли такая потоковая функция f:A^> Ng, обладающая следующими свойствами: /е) < с(е) для всех е g А; X f«P,q))- X f ((<3,r)) = 0 Для всех q g V, отличных отро и О,</)еЛ (q,r)eA go, Е f((P,<3o))- Е /((?о,г))>«; ^v(a)<k,rneA'={a&Atfa)*0}7 (p,qa)EA <М„г)еА а^А< 11. Триангуляция с ограничением. Заданы граф G = (V,E) и координаты x(p),y(p)&N каждой его вершины р g V на плоскости. Существует ли такое подмножество Е' с Е, что множество прямолинейных отрезков, соединяющих вершины из £', представляют триангуляцию множества точек И? 12. Целочисленный поток в сети с гомологичными дугами. Заданы орграф G=(V,A) с двумя выделенными вершинами р0 и q0, пропускные способности с(е) всех дуг е g А, потребность R g TV* и множество гомологических пар дуг Н c/j х А. Существует ли такая потоковая функция /: А —> Л/ что справедливы следу- ющие свойства: /е) < с(е) для всех дуг е g А; X f((p,g))~ (p,q)eA (q,i)eA для всех вершин q g V\ {p0, q0}; Ae)~Ae>) апя всех (e,A)eH', X /((A %))- X/feo>?))^^? (/>,<7„)e/ Gu,q)eA 13. Целочисленный поток в сети с расслоениями. Заданы орграф G = (Ц А) с двумя выделенными вершинамир0 и q0, разбиение А на подмножества А\, А2,..., At, про- пускные способности расслоений с1; с2,..., с* g кА, а также потребность R g TV*. Существует ли такая потоковая функция f-.A-y TVj, что выполнены следующие
1046 Часть III. Приложения дующие условия: Х/(е) < с, для всех у; X X /((6АЛ)) = ° Для се/у (р,<7)е/ (<7,л)е/ всех вершин qeV\{p0,q0}; X Ж А 9о )) ~ X Л(9о ? (р,%)е/- (9оЛ)еЛ 14. Целочисленный поток в сети с умножителями. Заданы орграф G = (И, А) с двумя выделенными вершинами, умножители для всех вершин р g V— {р0, q0}, пропускные способности с(е) g/V1’ всех дуг е&А и потребность /<’g/v'. Существует ли потоковая функция f: А —> No такая, что выполнены условия: Де) < с(е) для всех дуг ее А; X Л(?) ’/((А <?)) = Х^’г)) всех ? е Л \ {р0, ?0}; X /((А9))- Х/М^Л? (р,9)е/ (9оЛ)е^ 1.3.8. Множества и разбиения 1. К подмножеств. Заданы конечное множество А, веса и(а) всех элементов а е А и положительные целые числа К и IV. Верно ли, что существует не менее К различ- ных подмножеств А' с А, общие веса элементов которых не превышают И7? 2. 3-разбиение. Заданы множество А, состоящее из 3m элементов, число С е ,\Л и та- кие веса w(a) е ЛГ всех элементов a g А, что В/4 < S(a) < В/2 для всех a g А и об- щий вес элементов из А равен тВ. Можно ли разбить А на т попарно непересе- кающихся подмножеств, что общий вес элементов каждого из них равен В1 3. К векторов. Заданы подмножества Х\,Х2, ...,X„cN\ веса w(a) е N всех элемен- тов х е Xt u Х2 и ... о Хт и положительные целые числа К и W. Верно ли, что су- ществует не менее К различных таких ш-верных векторов (хь х2,..., хт) g g Xt х Х2 х Х„„ что X w(x/) ? 7=1 4. Базис семейства 3-множеств. Верно ли, что заданное семейство С подмножеств конечного множества S, в каждом из которых не более 3 элементов, содержит та- кое С с С, что | С’ | < К, где К — заданное положительное целое число, и для каж- дого подмножества А е С существует такое С"сС", что объединение подмно- жеств из С" совпадает с А? 5. Базис семейства множеств. Верно ли, что заданное семейство С подмножеств ко- нечного множества 5 содержит такое С с С, что | С | < К, где К — заданное по- ложительное целое число, и для каждого подмножества A g С существует такое С" с С", что объединение подмножеств из С" совпадает с А? 6. Матрица пересечений 3-множеств. Задана матрица А = (av) размера пхп с элемен- тами из Nq, в которой а,-, = 3 для всех I. Существуют ли такие подмножества Ci, С2,..., С„, что а,7= I C,n Q | для всех i и у?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1047 7. Матрица пересечений множеств. Задана матрица А = (а,у) размера пхп с элемен- тами из Л^. Существуют ли такие подмножества Сь С2,С„, что а,у= |С, п Су| для всех i и у? 8. Минимальное множество тестов. Верно ли, что заданное семейство С подмно- жеств конечного множества S содержит такое С' с С, что |С7'| < К, где К— задан- ное положительное целое число, и для каждой пары различных элементов х, у е S существует подмножество в С', содержащее ровно один из этих элементов? 9. Минимальное множество тестов для 3-множеств. Верно ли, что заданное семей- ство С подмножеств конечного множества S, в каждом из которых не более 3 эле- ментов, содержит такое С' с С, что|С'Ч< К, где К — заданное положительное целое число, и для каждой пары различных элементов х, yeS существует под- множество в С', содержащее ровно один из этих элементов? 10. Минимальное покрытие 3-множеств. Верно ли, что заданное семейство С под- множеств конечного множества S, в каждом из которых не более 3 элементов, содержит такое С' с С, что |С*| < К, где К — заданное положительное целое чис- ло, и любой элемент из 5 принадлежит по крайней мере одному подмножеству из С"? 11. Минимальное покрытие. Верно ли, что заданное семейство С подмножеств ко- нечного множества S содержит такое С'с С, что |С| < К, где К— заданное поло- жительное целое число, и любой элемент из 5 принадлежит по крайней мере од- ному подмножеству из С"? 12. Минимум суммы квадратов. Можно ли заданное конечное множество А, всем элементам а е А которого приписаны веса Уг(а)бЛ^, так разбить на заданное чис- ло к попарно непересекающихся подмножеств Ai, Л2,..., At, что Г У /=1 у < В , где В — заданное целое положительное число? 13. Множество представителей 2-множеств. Верно ли, что для заданного семейства С подмножеств конечного множества S, в каждом из которых не более 2 элемен- тов, существует такое подмножество S' с S, что |5"| < К, где К — заданное поло- жительное целое число, и S' содержит по крайней мере один элемент каждого подмножества из С? 14. Множество представителей. Верно ли, что для заданного семейства С подмно- жеств конечного множества S существует такое подмножество S’ с S, что |S'| < К, где К— заданное положительное целое число, и S' содержит по крайней мере один элемент каждого подмножества изС? 15. Общий вес. Существует ли такое подмножество X' заданного конечного множе- ства X, всем элементам х g X которого сопоставлены веса w(x) е N*, что общий вес элементов из X равен заданному целому положительному числу И? 16. Ограниченное точное покрытие 3-множествами. Заданы множество А, число эле- ментов которого кратно трем, и семейство С трехэлементных подмножеств мно-
1048 Часть III. Приложения жества X, ни один элемент которого не принадлежит более чем трем подмноже- ствам семейства. Верно ли, что существует такое С с С, что любой элемент из X принадлежит ровно одному подмножеству из С"? 17. Однородное сравнительное содержание. Верно ли, что для заданных семейств R и V подмножеств конечного множества X, существует подмножество X' с X, что число тех R, g R, для которых X' с R,, не меньше числа тех е R, что X' с Vft 18. Паросочетание с ограничениями по весу. Заданы непересекающиеся множестваX и Y, каждое из которых состоит из m элементов, веса w(a) g М всех элементов a 6 X\j У и вектор ограничений И7,, W2,..., IV,,,, где IV, е Л/*. Можно ли множество А = X u Y так разбить на m попарно непересекающихся подмножеств Ль А2, —, А,„, каждое из которых содержит по одному элементу из X и У, что для всех i общий вес элементов из А, равен И7,? 19. Произведение размеров. Существует ли такое подмножество А" заданного конеч- ного множества X, всем элементам х е X которого сопоставлены размеры л(л') е Л7', что произведение размеров его элементов равно заданному целому по- ложительному числу 5? 20. Разбиение. Существует ли такое подмножество X'заданного конечного множест- ва Л, всем элементам х g X которого сопоставлены веса w(x) g N\ что общий вес элементов из X' совпадает с общим весом элементов из Х\Х'. 21. Разбиение на равные подмножества. Существует ли такое подмножество X' за- данного конечного множества X, всем элементам х g X которого сопоставлены веса w(x) g М, что |А"| = |а'|/2 и общий вес элементов из X'совпадает с общим весом элементов из X \ Хг> 22. Расщепление 3-множеств. Задано семейство С подмножеств конечного множест- ва S, в каждом из которых не более 3 элементов. Существует ли такое разбиение S' на два непересекающихся подмножества, что ни одно подмножество из С не содержится целиком ни в одном из них? 23. Расщепление множеств. Задано семейство С подмножеств конечного множества S. Существует ли такое разбиение S' на два непересекающихся подмножества, что ни одно подмножество из С не содержится целиком ни в одном из них? 24. Сравнительное содержание. Верно ли, что для заданных семейств R и И подмно- жеств конечного множества X, всем элементам R, g R и I7 g V которых приписа- ны веса w(/?,), w(Vf) g М, существует подмножество Х'сХ, что суммарный вес тех R, g R, для которых X' с X, не меньше суммарного веса тех Vj g R, что Х'с Vjf 25. Точное покрытие 3-множествами. Заданы множество X, число элементов которо- го кратно трем, и семейство С трехэлементных подмножеств множества X. Верно ли, что существует такое С'с С, что любой элемент из X принадлежит ровно од- ному подмножеству из С? 26. Трехмерное сочетание. Существует ли такое подмножество М'заданного множе- ства Л'/сУх У х Z, где X, У, Z— попарно непересекающиеся множества, содер-
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1049 жащие по т элементов, что \М\ = т и никакие два различных элемента из М' не имеют ни одной одинаковой координаты? 27 Трехмерное сочетание для множества, совместимого по парам. Заданы X, Y, Z— попарно непересекающиеся множества, содержащие по т элементов, и совмес- тимое по парам множество MciX* Y х Z, т. е. для любых элементов a, b и с, имеет место свойство: если существуют элементы щ, х и у, что (а, Ь, у) е М, (а, х,с) & М и (w, b, с) е М, то (а, b, с) е М. Существует ли такое подмножество М' с Л/, что |Л/1 = т и никакие два различных элемента из М' не имеют ни одной одинаковой координаты? 28. Трехмерное сочетание с ограничениями по весу. Заданы попарно непересекаю- щиеся множества X, Y, Z, каждое из т элементов, веса w(a) е У' всех элементов а е A'u Y u Z число IV е N*. Можно ли так разбить множество А'и Y u Z на по- парно непересекающиеся подмножества А2,..., А„„ что каждое А, содержит по одному элементу из каждого множества A, Y. Z и общий вес элементов каждого А, равен И7? 29. Упаковка 3-множеств Верно ли, что заданное семейство С конечных множеств, в каждом из которых не более 3 элементов, содержит не менее заданного числа К попарно непересекающихся множеств? 30 Упаковка множеств. Верно ли, что заданное семейство С конечных множеств со- держит не менее заданного числа К попарно непересекающихся множеств? 1.3.9. Хранение и поиск 1. Группировка с помощью транспозиций. Существует ли последовательность, со- стоящая не более чем из заданного числа транспозиций соседних символов исход- ного заданного слова х е Е‘, которая превращает х в такое слово, у которого все вхождения любого символа а е Z образуют сплошной блок? 2. Дополнение до матрицы со свойством связности. Заданы двоичная матрица А раз- мера т х и и положительное целое число к. Существует ли такая матрица А', полу- чаемая из А заменой в ней не более к нулевых элементов единицами, что А' можно с помощью перестановок столбцов привести к виду, в котором в каждой строке все единицы расположены подряд? 3. Дополнение дд матрицы со свойством циклической связности. Заданы двоичная матрица А размера т хин положительное целое число к. Существует ли такая матрица Аполучаемая из А заменой в ней не более к нулевых элементов едини- цами, что А' можно с помощью перестановок столбцов привести к виду, в котором в каждой строке все единицы, либо все нули расположены подряд? 4. Кратчайшая общая подпоследовательность. Существует ли такое слово w в задан- ном алфавите Е, что |w| < К, где К— заданное положительное целое число, и каж- дое слово х е R, где R— заданное конечное множество слов в алфавите Е, может быть получено из м> удалением некоторых букв?
1050 Часть III. Приложения 5. Кратчайшая общая подпоследовательность в двоичном алфавите. Существует ли такое двоичное слово w, что |w| < К, где К — заданное положительное целое чис- ло, и каждое слово х е R, где R — заданное конечное множество двоичных слов, может быть получено из w удалением некоторых букв? 6. Кратчайшее общее надслово. Заданы алфавит Е, конечное множество R слов из Е* и положительное целое число к. Существует ли такое слово w е Е’длины, не превышающей к, которое содержит в качестве подслова каждое слово хе/?? 7. Кратчайшее общее надслово в двоичном алфавите. Заданы двоичный алфавит Е, конечное множество R слов из Е* и положительное целое число к. Существует ли такое слово w е Z* длины, не превышающей к, которое содержит в качестве под- слова каждое слово хе/?? 8. Минимизация числа блоков. Задана двоичная матрица А размера m х п и положи- тельное целое число к. Существует ли такая перестановка столбцов матрицы А, что получившаяся в результате матрица В имеет не более к блоков из последова- тельно идущих единиц? 9. Общая подпоследовательность наибольшей длины. Заданы алфавит Е, конечное множество R слов из Е‘ и положительное целое число к. Есть ли такое слово w е Е* длины не меньшей к, которое можно получить из любого слова хе/? пу- тем удаления некоторых букв? 10. Ограниченная минимизация числа блоков. Задана двоичная матрица А размера m х и и положительное целое число к. Существует ли такая перестановка столб- цов матрицы А, что в получившейся в результате матрице В имеется не более к таких пар индексов, что bit = 1 и либо й,,+| = 0, либо j = и и Ьп = 0? 11. Ограниченное разбиение со свойством связности. Заданы алфавит Е, семейство {Ei, Е2, , его таких подмножеств, что |Е| < 5, и положительное целое число к. Существует ли такое разбиение Е на попарно непересекающиеся подмножества Xt, Х2, —,Хк, что каждое Xt имеет не более одного общего элемента с каждым Е7 и для каждого индекса j, 1 <j <п, существует такой индекс I, что Е, cJf/u^/+lu...uJf,+|£j_I? 12. Ограниченное сжатие разреженной матрицы. Задана двоичная матрица А раз- мера m х и и положительное целое к, к<пт. Существуют ли такая целочислен- ная последовательность Ь\, Ь2,..., Ь„+к и такая функция s : {1, 2, ..., т} -> 2, 3,..., к}, что для всех i и j элемент au равен 1 тогда и только тогда, когда W+J = /? 13. Ограниченное соответствие. Заданы алфавит Е, две последовательности хь х2,..., х„ и yh у2,..., у„ слов из Е* и положительное целое число к < и. Существу- ет ли такая последовательность индексов ц, i2,..., i„ где t<k, что слова х/5х( ,...,х,( и д,^,2,...,д совпадают? 14. Однородное размещение файла с дублированием. Задан граф G = (И, Е), для каж- дой вершины ре V которого известны количество обращений u(p) е /V* и стой-
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1051 мость запоминания s(p) е N\ а также целое положительное число К. Существует ли такое подмножество И'g V, что s(p) + ^d(p) u(p) < К, где d(p) — дли- реИ' peV на кратчайшего пути в G от р до множества V', если все вершины имеют одина- ковые количества обращений и одинаковые стоимости запоминания? 15. Ожидаемая стоимость поиска. Заданы множество записей R, такие вероятности р(г) обращения к записям г е R, что их сумма равна 1, число сегментов и еМи положительное целое число К. Существует ли такое разбиение R на попарно не- пересекающиеся подмножества Rt, R2,..., R„„ что />(/?,)•p(Rj) d(i, J) < К, где />(/?,) = У р(г) и величина d(i,j) равна j — / - 1, если / < j, и равна т — i + j — 1, re«, если j < i? 16. Ожидаемая стоимость поиска в фиксированном числе сегментов. Имеется фик- сированное число сегментов т > 1. Заданы множество записей R, такие вероятно- сти р(г) обращения к записям г е R, что их сумма равна 1, и положительное целое число К. Существует ли такое разбиение R на попарно непересекающиеся под- множества R\, R2,..., R„„ что /?(/?,) • ,) • J(Z, /) < К , где pfR,) = У р(г) и величина d(i,j) равна j - i - 1, если i < j, и равна m - i +j - 1, если j < i. 17. Организация памяти в виде корневого дерева. Заданы конечное множество X, семейство Х\, Х2, ...,Х„ подмножеств множества X и положительное целое чис- ло К. Существует ли такое семейство Х(,Х2,...,Х;ъ что А^'сХ( для всех /, Y1 У |2Г' - < К и элементы всех подмножеств Х(, Х2, —,Х£ образуют пути в не- /=1 котором корневом дереве? 18. Подматрица со свойством связности. Заданы матрица А размера тихи, образован- ная из цифр 0 и 1, а также положительное целое число к. Существует ли в А такая подматрица В размера т х к, что с помощью перестановки столбцов можно при- вести В к виду, в которой в каждой строке все единицы идут подряд? 19. Подматрица со свойством циклической связности. Заданы двоичная матрица А размера т х и и положительное целое число к. Существует ли в А такая подмат- рица В размера т х к, что с помощью перестановки столбцов можно привести В к виду, в которой в каждой строке все единицы либо все нули идут подряд? 20. Подстановка регулярного алфавитом Y и слово у е У*. Существуют ли в языках, определяемых выражениями R, Rt, R2,..., R,„ такие слова w, wh w2,w„ со- ответственно, что выражения. Заданы два алфавита Х= {хь х2,х„} и У = {уьУ2, —,Уи}, регулярное выражение R в алфавите XkJ Y, регулярные выра- жения R], R2,..., R„ над алфавитом Y и слово у е У*. Если заменить в слове w каж- дое вхождение символа х, на слово то получившееся в результате слово будет совпадать с у?
1052 Часть III. Приложения 21. Представление со свойством связности. Заданы алфавит Е, семейство {Еь Е2, —, 2„} подмножеств множества Е и положительное целое число к. Суще- ствует ли такое слово х g Е, что | х | < к и для всех i элементы множества Е, обра- зуют в слове х подслово длины IЕ, | ? 22. Прямоугольное сжатие картинки. Можно ли покрыть заданным числом прямо- угольников все единичные элементы заданной матрицы, состоящей из 0 и 1 ? 23. Разбиение на матрицы со свойством связности. Можно ли так разбить строки за- данной двоичной матрицы на две подгруппы, чтобы каждую из получаемых в ре- зультате матриц с помощью перестановок столбцов можно было привести к виду, в котором в каждой строке все единицы расположены подряд? 24. Разбиение со свойством связности. Заданы алфавит Е и семейство {Еь Е2,..., Е,,} подмножеств Е. Существует ли такое разбиение Е на попарно непересекающиеся подмножества Х\,Х2, ...,Хк, что каждое Л, имеет не более одного общего элемента с каждым Е7 и для каждого индекса /, 1 <j < и, существует такой индекс /, что Еу с X, ^->Xl+i O...CJ A,+|e р ? 25. Размещение файла с дублированием. Задан граф G = (Г, Е), для каждой вершины р е V которого известны количество обращений и(р) е W' и стоимость запомина- ния s(p) еМ, а также целое положительное число К. Существует ли такое под- множество И'ст V, что У s{p) + У d(p) u(p) < К, где d(p) — длина кратчайше- реИ’ peV го пути в G отр до множества V? 26. Редактирование слова. Заданы алфавит Е, два слова х,у е Е* и положительное целое число к. Можно ли получить из слова х слово у, применив не более к опе- раций вычеркивания символа и перестановки соседних символов9 27. Сжатие разреженной матрицы. Заданы двоичная матрица А размера тх п (эле- менты матрицы — это цифры 0 и 1) и положительное целое число к < т и. Су- ществуют ли такая целочисленная последовательность Ь\, Ь2,..., Ь„,к и такая функция л : {1,2,..., т} —> {1, 2,..., к}, что для всех i и j элемент а,, равен 1 тогда и только тогда, когда Ац/д/ = «? 28. Упаковка в крнтейнеры. Заданы конечное множество предметов X, размеры ,s(x) е 7V* всех предметов х е X. вместимость одного контейнера S е У и положи- тельное число К. Существует ли такое разбиение X на попарно непересекающие- ся подмножества ХЬХ2, —,ХК, что сумма размеров всех предметов каждого из подмножеств не превосходит S? 29. Упаковка в фиксированное число контейнеров. Имеется фиксированное число К> 1 контейнеров. Заданы конечное множество предметов X, размеры л(х) е М всех предметов хе/, вместимость одного контейнера SeM. Существует ли та- кое разбиение X на попарно непересекающиеся подмножества Xlt Х2, —,Хк, что сумма размеров всех предметов каждого из подмножеств не превосходит S ?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1053 1.3.10. Программы и схемы 1. Вычисление семейства. Заданы семейство С подмножеств конечного множества А и положительное целое число к. Существует ли последовательность операторов объединения z\ <— %! z2 <— х2 ^>У2, -т <— х,„ иу„„ где т < к, для всех i каж- дое из х, и у, есть либо {а} для некоторого а е А, либо z7 для некоторого j <i, при- чем х, и у, не пересекаются и для каждого подмножества с е С найдется такой номер z, что с совпадает с z,? 2. Генерация кода для параллельных присваиваний. Можно ли упорядочить задан- ные п присваиваний с попарно различными переменными в левых частях таким образом, чтобы существовало не более заданного числа таких переменных х, что оператор присваивания переменной х предшествует хотя бы одному присваива- нию, правая часть которого содержит х? 3. Генерация кода на одноадресной регистровой машине. Задан дэг (7 = (Г, А) ли- нейного участка, у которого степени захода всех вершин не превышают 2, и по- ложительное целое число. Существует ли такая программа для одноадресной ре- гистровой машины, которая эквивалентна дэгу и содержит не более к команд? 4. Генерация кода с неограниченным числом регистров. Задан дэг G = (И, А) линей- ного участка, каждая вершина которого имеет степень захода не превышаю- щую 2, и целое число к. Существует ли программа для регистровой машины дли- ны не более к, которая является эквивалентной линейному участку? 5. Допустимость назначения регистров. Задан дэг G = (У, А) линейного участка, по- ложительное целое число к и назначение регистров г: И-> {/?,,..., /?*}. Сущест- вует ли такое корректное вычисление G на регистровой машине, которое не противоречит назначению регистров г? 6. Достаточность числа регистров. Задан дэг G= (У, А) линейного участка и поло- жительное целое число к. Существует ли вычисление G на регистровой машине, использующее не более к регистров? 7. Несвободность моноидной ациклической стандартной схемы с двумя перемен- ными. Задана ациклическая стандартная схема, все функциональные и предикат- ные символы которой являются унарными и которая содержит две переменных. Верно ли, что схема не является свободной? 8. Несвободность моноидной стандартной схемы без циклов. Задана стандартная схема, все функциональные и предикатные символы которой являются унарными и которая является ациклической, т. е. не содержит циклов в управляющем графе. Верно ли, что схема не является свободной? 9. Неэквивалентность ациклических схем Янова. Верно ли, что две заданные схемы Янова, не содержащие циклы, не являются функционально эквивалентными? 10. Неэквивалентность композиций сложения и деления по модулю. Являются ли не- эквивалентными два заданных выражения, построенных над конечным множест- вом переменных с использованием следующих функций: plus(x, у) =х + у и mod(x,к) = х-Л-|х/к], гдех,у — переменные?
1054 Часть III. Приложения 11. Неэквивалентность композиций сложения и максимума. Являются ли неэкви- валентными два заданных выражения, построенных над конечным множест- вом переменных с использованием следующих функций: р(х) = тах{х — 1,0}, plufix, у) = х + у, где х, у -— переменные? 12. Неэквивалентность композиций условных функций. Являются ли неэквивалент- ными два заданных выражения, построенных над конечным множеством пере- менных с использованием функции ifix, у) = if у = 0 then х else 0, где х, у — пере- менные? 13. Неэквивалентность линейных программ с массивами. Заданы конечные множест- ва переменных X, массивов М, операций F и две программы Р} и Р2, являющиеся последовательностями операторов присваивания одного из следующих трех ви- дов: х0<— /[х,,х2,..., хг); Л[х,]<—х7; х, <—Л[х,], где х0, хь х2,..., xr е X— перемен- ные, А е М— массив,/е F— операции, обрабатывающие значения из некоторо- го конечного множества V. Являются ли программы Pi и Р2 неэквивалентными, т. е. существуют ли такие начальные значения переменных и массивов, что для некоторой переменной из X программы дадут различные значения? 14. Неэквивалентность линейных программ с условными присваиваниями. Заданы конечное множество переменных X, каждая из которых может принимать значе- ния из конечного множества F, и две программы Р, и Р2, представляющие собой последовательности операторов присваивания вида "х0<—if Xi =х2 then x3else х4". Являются ли программы неэквивалентными? 15. Неэквивалентность моноидных рекурсивных схем. Заданы конечные множества символов функций F и символов предикатов Р и две рекурсивные схемы, каждая из которых имеет вид непустого конечного множества определений вида/х) = if р(х) then g(x) else Л(х), где f,g,heF,p&P, а также основного вызова fix). Являются ли схемы не функционально эквивалентными? 16. Неэквивалентность программ без вложенных циклов. Верно ли, что не эквива- лентны две заданные программы, каждая из которых является последователь- ностью операторов вида х <— у, х <— х + 1, х <— 0, loop х и end, где х и у — элемен- ты конечного множества переменных, и не содержит вложенных циклов (т. е. в ней между любыми двумя вхождениями операторов loop всегда находится опера- тор end)? 17. Неэквивалентность программ с конечной памятью. Заданы конечное множество переменных X, каждая из которых может принимать значения из конечного мно- жества значений {$}, две программы Р, и Р2, каждая из которых — это по- следовательность 1 : 2 : S2;...; п : S„, занумерованных операторов S, вида: x,<r-Vj, if Vt = Fj goto к; read X; write Vf, accept; halt, где xt e Хи Vje X<u {$} u V. Являются ли программы неэквивалентными? 18. Неэквивалентность простых функций. Являются ли неэквивалентными два заданные выражения, построенные над конечным множеством переменных с использованием следующих функций: s(x) = x+l, /?(х) = тах{х-1,0}, plusfx, у) = х + у, div(x, к)—[х/к], mod(x, А) = х — к • Гх/Л], ifix, у) = if у = 0 then х else 0, case"fat, х2,..., х„) = хк, где х, у, х>, х2,..., х„ — переменные, к е Nfi
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1055 19. Неэквивалентность схем Янова. Верно ли, что две заданные схемы Янова не яв- ляются функционально эквивалентными? 20. Ограниченная генерация кода для параллельных присваиваний. Можно ли упоря- дочить заданные и присваиваний, в каждом из которых не более двух перемен- ных в правой части, с попарно различными переменными в левых частях таким образом, чтобы существовало не более заданного числа таких переменных х, что оператор присваивания переменной х предшествует хотя бы одному присваива- нию, правая часть которого содержит х? 21. Ограниченная генерация кода на одноадресной регистровой машине. Задан дэг G = (И, А) линейного участка, у которого степени захода всех вершин не превы- шают 2, причем все вершины, имеющие степень больше 1, соединены дугами только с висячими вершинами, и положительное целое число к. Существует ли такая программа для одноадресной регистровой машины, которая содержит не более к команд? 22. Ограниченная допустимость назначения регистров. Задан дэг G = (И, А) линейно- го участка, степени всех вершин которого не превышают 2, положительное целое число к и назначение регистров г : И—>{/?ь..., /?*.}. Существует ли такое коррект- ное вычисление G на регистровой машине, которое не противоречит назначению регистров г? 23. Ограниченная достаточность числа регистров. Задан дэг G = (Г, А) линейного участка, степени всех вершин которого не превышают 2, и положительное целое число к. Существует ли вычисление G на регистровой машине, использующее не более к регистров? 24. Ограниченная неэквивалентность линейных программ с массивами. Заданы ко- нечные множества переменных X, массив А и две программы Pt и Р2, являющие- ся последовательностями операторов присваивания одного из следующих двух видов: Л[х,] <- х} и х, <- A[xj], где х„ х, е X— переменные. Являются ли програм- мы Р] и Р2 неэквивалентными, т. е. существуют ли такие начальные значения пе- ременных и массивов, что для некоторой переменной из X программы дадут раз- личные значения? 25. Ограниченная неэквивалентность линейных программ с условными присваива- ниями. Заданы конечное множество переменных X, каждая из которых можез принимать двоичные значения, и две программы и Р2, представляющие собой последовательности операторов присваивания вида "х0<—if х( = х2 then х3 else х4". Являются ли программы неэквивалентными? 26. Ограниченная неэквивалентность схем Янова. Верно ли, что две заданные схемы Янова, построенные с помощью одной функции и одного предиката, не являются функционально эквивалентными? 27. Ограниченное вычисление семейства. Заданы семейство С подмножеств конеч- ного множества А, каждое из которых содержит не более 3 элементов, и положи- тельное целое число к. Существует ли последовательность операторов объедине- ния Z| <- х, z2 «- х2 <->у2, zm <- xmuy„„ где т < к, для всех i каждое из х, и
1056 Часть III. Приложения у, есть либо {а} для некоторого а е А, либо z; для некоторого j < i, причем х, и у, не пересекаются и для каждого подмножества с е С найдется такой номер г, что с совпадает со значением z,1 1.3.11. Автоматы и языки 1. Допускаемость детерминированным ЛО-автоматом. Верно ли, что заданный де- терминированный линейно-ограниченный автомат допускает заданное слово? 2. Допускаемость ЛО-автоматом. Верно ли, что заданный линейно-ограниченный автомат допускает заданное слово? 3. Минимальное разделяющее регулярное выражение. Заданы алфавит Е, два ко- нечных подмножества S, R с X’ и положительное целое число к. Существует ли такое регулярное выражение на Е, содержащее не более к символов из Е, что оп- ределяемый им язык содержит все слова из S и не содержит ни одного слова из R? 4. Минимальный разделяющий конечный автомат. Заданы алфавит Е, два конечных подмножества S,/?сЕ* и положительное целое число к. Существует ли такой конечный автомат с к состояниями, что распознаваемый им язык содержит все слова из S и не содержит ни одного слова из R? 5. Неуниверсальность регулярного выражения. Верно ли, что заданное регулярное выражение над двоичным алфавитом не представляет язык всех двоичных цепо- чек? 6. Неуниверсальность регулярной грамматики. Верно ли, что заданная регулярная грамматика с двоичным терминальным алфавитом не порождает язык всех дво- ичных цепочек? 7. Неэквивалентность конечных автоматов. Верно ли, что два заданных недетерми- нированных конечных автомата А} и А2 с общим входным алфавитом Е задают разные языки? 8. Неэквивалентность регулярных выражений. Верно ли, что два заданных регуляр- ных выражения над одним и тем же алфавитом представляют различные языки? 9. Неэквивалентность регулярных грамматик. Верно ли, что две заданные регуляр- ные грамматики порождают разные языки? 10. Ограниченная неэквивалентность конечных автоматов. Верно ли, что два задан- ных недетерминированных конечных автомата А\ и А2 с общим входным одно- элементным алфавитом задают разные конечные языки? 11. Ограниченная неэквивалентность конечных автоматов с общим одноэлементным входным алфавитом. Верно ли, что два заданных недетерминированных конеч- ных автомата Л । и А2 с общим одноэлементным входным алфавитом задают раз- ные языки? 12. Ограниченная неэквивалентность регулярных выражений. Верно ли, что пред- ставляют различные языки два заданных регулярных выражения, которые не со- держат * и определены над одним и тем же алфавитом9
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1057 13. Ограниченное минимальное разделяющее регулярное выражение. Заданы алфа- вит Е, два конечных подмножества S, R g Е* и положительное целое число к. Существует ли такое регулярное выражение на Е, содержащее не более к симво- лов из Е, что в нем нет операции объединения, а определяемый им язык содержит все слова из S и не содержит ни одного слова из /?? 14. Пересечение для конечных автоматов. Существует ли слово, допускаемое каж- дым конечным автоматом из заданного конечного множества, имеющих общий входной алфавит? 15. Покрытие Рейнольдса для КС-грамматик. Верно ли, что для двух заданных КС- грамматик С/| = (Nb Eb Р}, S,) и G2 = (N2, Е2, Р2, S2), где Е| = Е2 = существует такая функция f : Nt u Е, -> N2 u E2, чтоДх) = x для всех xeE, fiA)&N2, для всех A e. Nt, J(S]) = S2 и для каждой продукции вида А ->xtx2... х„ из Р\ ее образ f(A) ->/(Х|)/(х2) .../(хп) является продукцией из Р2? 16. Покрытие Рейнольдса для регулярных грамматик. Верно ли, что для двух задан- ных регулярных грамматик G, = Eh Pt, S() и G2 = (N2, Е2 Pi, Si), где E, = E2 = E, существует такая функция /: Nt и E] -> N2 u E2, что/(х) =x для всех x e E, fiA) e /V2 для всех A e flSt) = S2, и для каждой продукции вида А -> X! х2 ... х„ из Pt ее образДЛ) ->/(xi)Ахг) —flxi) является продукцией из Р2? 17. Принадлежность детерминированному КЗ-языку. Верно ли, что заданная цепоч- ка принадлежит языку, порождаемому заданной детерминированной КЗ-грам- матикой? 18. Принадлежность КЗ-языку. Верно ли, что заданная цепочка принадлежит языку, порождаемому заданной КЗ-грамматикой? 19. Редукция не полностью определенного конечного автомата. Можно ли функцию перехода заданного конечного автомата так продолжить до всюду определенной, чтобы получить полностью определенный конечный автомат, для которого суще- ствует эквивалентный с числом состояний, не превышающим заданного числа А? 20. Редукция полностью определенного недетерминированного конечного автомата. Существует ли для заданного полностью определенного недетерминированного конечного автомата эквивалентный детерминированный конечный автомат с чис- лом состояний, не превышающим заданного числа к? 21. Структурная неэквивалентность грамматик. Верно ли, что для двух заданных КС- грамматик являются неэквивалентными грамматики, получаемые из исходных заменой каждой продукции вида А -> х на продукцию А -» (х), где "("и")" — но- вые терминальные символы? 22. Структурная неэквивалентность регулярных грамматик. Верно ли, что для двух заданных регулярных грамматик с двоичным терминальным алфавитом являются неэквивалентными грамматики, получаемые из исходных заменой каждой про- дукции вида Л —> х на продукцию А —> (х), где "("и")" — новые терминальные символы?
1058 Часть III. Приложения 23. Фиксированная редукция не полностью определенного конечного автомата. Фик- сировано целое число к >6. Можно ли функцию перехода заданного конечного автомата так продолжить до всюду определенной, чтобы получить полностью определенный конечный автомат, для которого существует эквивалентный с чис- лом состояний, не превышающим Л? 1.3.12. Логика 1. 3-выполнимость. Существует ли для заданного набора дизъюнкций, каждая из которых состоит из 3 литералов, выполняющий набор истинных значений? 2. 3-выполнимость при одном истинном литерале. Существует ли для заданного на- бора дизъюнкций, каждая из которых состоит из 3 литералов, такой выполняю- щий набор истинностных значений, что для каждой дизъюнкции набора имеется в точности один истинный литерал? 3. 3-выполнимость при различных литералах. Существует ли для заданного набора дизъюнкций, каждая из которых состоит из 3 литералов, такой выполняющий на- бор истинности, что в каждой дизъюнкции набора найдется по крайней мере один истинный литерал и один ложный литерал? 4. Выполнимость. Существует ли для заданного набора дизъюнкций выполняющий набор истинных значений? 5. Выполнимость булевых выражений. Существует ли набор истинных значений переменных, при котором истинно заданное булевое выражение? 6. Выполнимость булевых выражений над полным набором связок. Существует ли набор истинных значений переменных, при котором истинно заданное булевое выражение, использующее фиксированный полный набор булевских связок? 7. Максимальная 2-выполнимость. Существует ли для заданного набора дизъюнк- ций, каждая из которых состоит ровно из 2 литералов, такой набор истинных значений, что выполняется не менее заданного числа дизъюнкций исходного на- бора? 8. Минимальная дизъюнктивная нормальная форма. Заданы множество переменных U= {щ, «2, •••, и„}, множество А = {0, 1}" наборов истинностных значений и по- ложительное целое число к. Существует ли над множеством U такая дизъюнк- тивная нормальная форма Е, содержащая не более к дизъюнктивных членов, что Е истинна только на наборах истинностных значений из А? 9. Монотонная 3-выполнимость. Существует ли для заданного набора дизъюнкций, каждая из которых состоит из 3 литералов и содержит только сами переменные или их отрицания, выполняющий набор истинных значений? 10. Ограниченная 3-выполнимость при одном истинном литерале. Существует ли для заданного набора дизъюнкций, каждая из которых состоит из 3 литералов и не содержит отрицаний переменных, такой выполняющий набор истинностных значений, что для каждой дизъюнкции набора имеется в точности один истинный литерал?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1059 11. Ограниченное отсутствие тавтологии. Верно ли, что для заданного булевого вы- ражения, находящегося в дизъюнктивной нормальной форме, каждый дизъюнк- тивный член которой содержит не более трех литералов, существует такой набор истинностных значений переменных, что булевое выражение принимает ложное значение? 12. Отсутствие тавтологии. Верно ли, что для заданного булевого выражения, ис- пользующего булевские связки —>, v, л, —существует такой набор истинностных значений переменных, что булевое выражение принимает ложное значение? 1.3.13. Игры и головоломки 1. Выполнение 3-формулы. Рассматривается игра с заданными множеством пере- менных X и семейством дизъюнкций С над X, каждая из которых содержит 3 лите- рала, в процессе которой два игрока поочередно выбирают по одной новой пере- менной из X и присваивают им логические значения. Выигрывает тот игрок, кото- рый приводит к выполнению всех дизъюнкций из С. Существует ли у первого игрока выигрышная стратегия для заданных Хи С? 2. Выполнение формулы. Рассматривается игра с заданными множеством перемен- ных X и семейством дизъюнкций С над X, в процессе которой два игрока пооче- редно выбирают по одной новой переменной из X и присваивают им логические значения. Выигрывает тот игрок, который приводит к выполнению всех дизъюнк- ций из С. Существует ли у первого игрока выигрышная стратегия для заданных ХиС? 3. "Го" на доске п х п. Есть ли у игрока, имеющего право сделать первый ход, выиг- рышная стратегия при игре в "го" в заданной позиции расположения белых и чер- ных фишек на расширенной доске размером и х и? 4. Максимальное взвешенное паросочетание. Рассматривается игра на заданном гра- фе G = (V, Е), ребрам е е Е которого приписаны веса w(e) е N\ при которой два игрока поочередно выбирают по одному новому ребру, не имеющему общих кон- цов с выбранными ранее ребрами. Как только сумма всех выбранных ребер пре- восходит k е N\ первый игрок выигрывает. Имеет ли первый выигрышную стра- тегию для заданных G и к? 5. Накрывающее множество. Рассматривается игра на заданном конечном множестве А" и семействе С его подмножеств, в процессе которой два игрока поочередно выби- рают элементы из X до тех пор, пока для каждого У е С не окажется выбранным какой-то элемент из У. Игрок, ход которого приводит к этой ситуации, проигрыва- ет. Имеет ли первый игрок выигрышную стратегию при игре на заданных А-и С? 6. Облицовка квадрата. Заданы конечное множество красок С, множество плиток, любая из четырех сторон каждой из которых окрашена в один из цветов, и поло- жительное целое число к < |С|. Можно ли замостить квадрат размера п х и плитка- ми из Т таким образом, чтобы краски сторон соприкасающихся плиток совпадали?
1060 Часть III. Приложения 7. Обобщенная география. Рассматривается игра на заданном орграфе G = (К, А) с выделенной вершиной р0 е И, в процессе которой два игрока поочередно выби- рают по одной новой (еще не выбранной) дуге. Первая выбранная дуга должна исходить из р0, а каждая последующая выбранная дуга должна исходить из вер- шины, в которую заходит дуга, выбранная до этого последней. Игрок, который первым окажется не в состоянии выбрать новую дугу, проигрывает. Имеет ли для заданного орграфа G первый игрок выигрышную стратегию? 8. Обобщенная игра в кубики. Заданы конечное множество С красок, множество Q кубиков, число которых совпадает с числом красок, а грани каждого из которых окрашены в заданные цвета из С. Можно ли сложить кубики Q в такой столбик, чтобы каждый цвет появлялся на каждой из четырех сторон столбика ровно один раз? 9. Обобщенная планарная география. Рассматривается игра на заданном двудоль- ном планарном орграфе G — (V, А), имеющего степени захода и исхода, не пре- восходящие 2, со степенями вершин, не превосходящими 3, и с выделенной вер- шиной ро е V, в процессе которой два игрока поочередно выбирают по одной но- вой (еще не выбранной) дуге. Первая выбранная дуга должна исходить из р0, а каждая последующая выбранная дуга должна исходить из вершины, в которую заходит дуга, выбранная до этого последней. Игрок, который первым окажется не в состоянии выбрать новую дугу, проигрывает. Имеет ли для заданного орграфа G первый игрок выигрышную стратегию? 10. Обобщенные "Кейли". Рассматривается игра за заданном графе G = (И, Е), в про- цессе которой два игрока поочередно выбрасывают из графа по одной вершине вместе со всеми инцидентными ей ребрами. Выигрывает тот игрок, который уда- ляет последнюю вершину. Есть ли для заданного графа выигрышная стратегия у первого игрока? 11. Обобщенные "Кейли” на двудольном графе. Рассматривается игра за заданном двудольном графе, в процессе которой два игрока поочередно выбрасывают из графа по одной вершине из своей доли вместе со всеми инцидентными ей ребра- ми. Выигрывает тот игрок, который удаляет последнюю вершину. Есть ли для за- данного графа выигрышная стратегия у первого игрока? 12. Обобщенный "гекс". Рассматривается игра на заданном графе G = (И, Е) с двумя выделенными вершинами a, t е И, в процессе которой два игрока поочередно вы- бирают по одной вершине из И\ {5, Z}, причем вершины, выбранные одним игро- ком, окрашиваются в синий цвет, а выбранные другим — в красный. Игрок вы- игрывает, если построит путь по G от а к t, проходящий только через вершины его цвета. Имеет ли первый игрок выигрышную стратегию для заданного G? 13. Обобщенный ориентированный "гекс". Рассматривается игра на заданном оргра- фе G = (E, А) с двумя выделенными вершинами a, Ze К, в процессе которой два игрока поочередно выбирают по одной вершине из Е\ {s, Z}, причем вершины, выбранные одним игроком, окрашиваются в синий цвет, а выбранные другим — в красный. Игрок выигрывает, если построит путь по G от а к Z, проходящий
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1061 только через вершины его цвета. Имеет ли первый игрок выигрышную стратегию для заданного G? 14. Обобщенный ориентированный реберный "гекс". Рассматривается игра на задан- ном орграфе G с двумя выделенными вершинами $ и t, в процессе которой два игрока поочередно выбирают по одной дуге, причем дуги, выбранные одним иг- роком, окрашиваются в синий цвет, а выбранные другим — в красный. Игрок выигрывает, если построит путь по G от 5 к t, проходящий только по дугам его цвета. Имеет ли первый игрок выигрышную стратегию для заданного G? 15. Ограниченное присвоение истинности с разбиением множества переменных. Рас- сматривается игра с заданными множеством переменных X и семейством дизъ- юнкций С над X, не содержащих отрицаний, в процессе которой два игрока по- очередно выбирают по одной новой переменной из X до тех пор, пока не будут выбраны все переменные. Выигрывает первый игрок, если игра приводит к вы- полнению всех дизъюнкций из С на таком наборе значений истинности, который равен 1 для переменных, выбранных им, и равен 0 для переменных, выбранных противником. Существует ли у первого игрока выигрышная стратегия для задан- ных X и С? 16. Присвоение истинности с разбиением множества переменных. Рассматривается игра с заданными множеством переменных А" и семейством дизъюнкций С над X, в процессе которой два игрока поочередно выбирают по одной новой перемен- ной из X до тех пор, пока не будут выбраны все переменные. Выигрывает первый игрок, если игра приводит к выполнению всех дизъюнкций из С на таком наборе значений истинности, который равен 1 для переменных, выбранных им, и равен О для переменных, выбранных противником. Существует ли у первого игрока вы- игрышная стратегия для заданных А'и С? 17. Составление кроссворда. Можно ли составить кроссворд из слов заданного ко- нечного множества слов, размещая буквы слов в нулевые клетки заданной мат- рицы из нулей и единиц размером «хи? 18. Уничтожение. Заданы дэг G = (V,A), семейство С = {At,A2, —,Ат} подмножеств множества А, функция раскраски f: И -» {0, 1,..., т}, где/(р) = z > О означает, что пометка типа i присвоена вершине р, a f0(p) = 0 означает, что вершина р не поме- чена. Рассматривается игра, в процессе которой два игрока поочередно произво- дят изменение раскраски (функции/) следующим образом. Игрок выбирает неко- торую вершину р е V с пометкой /(р) > 0 и дугу (р, q) е А^у, что приводит к из- менению ftp) ufiq) : р становится непомеченной, a q либо получает пометку ftp), если q не была ранее помечена, либо становится непомеченной. Игрок выигрыва- ет, если его противник неспособен сделать ход. Есть ли у первого игрока выиг- рышная стратегия для заданных G,Cwf? 19. Фильтр. Рассматривается игра на конечном множестве X и двух семействах А и В его подмножеств в процессе которой два игрока поочередно выбирают элементы из X до тех пор, пока множество X' всех выбранных элементов не будет пересе- каться с каждым подмножеством из А, либо с каждым подмножеством из В. Пер- вый игрок выигрывает тогда и только тогда, когда X' пересекается с каждым
1062 Часть III. Приложения подмножеством из В, причем, если последний ход сделал он, то X' не должен пе- ресекаться с каждым подмножеством из А. Есть ли у первого игрока выигрышная стратегия для заданных X, А и В? 20. Шашки на доске«хп. Есть ли у игрока, имеющего право сделать первый ход, выигрышная стратегия при игре в шашки в заданной позиции расположения бе- лых и черных дамок на расширенной доске размером и х л? 1.3.14. Алгебра и теория чисел 1. Вычисление перманента. Задана двоичная матрица М размера и х и и положитель- ное целое число к < и!. Верно ли, что значение перманента матрицы М равно Л? П1 ь 2. Делимость показательного выражения. Делится ли число [(<? ' -1) на число ./=1 п -1), где aj и bj— заданные положительные целые числа и q— заданное /=! целое число? 3. Квадратичные сравнения. Заданы положительные целые числа a, b и с. Существу- ет ли такое положительное целое число х < с, что х2 = t/(mod 6)? 4. Квадратные диофантовы уравнения. Для заданных положительных целых чисел а, Ь, с существуют ли такие положительные целые числа х и у, что ах2 + by = с? 5. Неэквивалентность целочисленных выражений. Верно ли, что представляют раз- ные множества два заданных целочисленных выражения еь е2 е Е, где Е опреде- ляется рекурсивно по следующим правилам: (1) двоичное представление числа и е Nесть целочисленное выражение, представляющее множество {и}; (2) если г и I есть два целочисленных выражения, представляющие R и L, то г и / и г + I также являются целочисленными выражениями, которые представляют множества R<j L и {m + и : т е R,n е L} соответственно? 6. Ограниченная делимость показательного выражения. Фиксировано число q, |<?| > 1. т п Делится ли число на число , где а, и bi — заданные поло- ./=1 '=1 жительные целые числа, являющиеся произведениями различных простых чисел? 7. Ограниченная сравнительная делимость. Заданы две последовательности <7Ь а2, ..., «„ и bt, b2,... Ь„ положительных целых чисел, каждая из которых не содержит один и тот же элемент дважды. Существует ли положительное целое число с, для кото- рого количество таких I, что с делит d„ больше числа таких j, что с делит А,? 8. Ограниченная унификация для конечно определенных алгебр. Являются ли уни- фицируемыми два терма s, t е 7(S), построенные над конечной сигнатурой S задан- ной эквациональной спецификации (S, Е), где Е— множество равенств вида r = I между термами r,l& 7(S), один из которых не содержит символов переменных?
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1063 9. Ограниченная унификация с коммутативными операциями. Существует ли уни- фикатор для двух заданных термов, построенных из констант и переменных с помощью скобок и коммутативной бинарной операции, каждый из которых со- держит не более 7 вхождений констант и переменных? 10. Периодическое решение рекуррентного уравнения. Задана последовательность (ci, 61), (с2, Ь2), ..., (с„, 6„) упорядоченных пар целых чисел с положительными 6,. Существует ли такая последовательность целых чисел а0, <д,..., я„ ь где н>тах{6ь Ь2,..., b^i}, что бесконечная последовательность я0,Я|, —, определяе- т мая рекуррентным уравнением я, -а,_ь для всех i>n, удовлетворяет со- отношению а, = я,(mod п)? 11. Представимость целочисленным выражением. Заданы целое число к и целочис- ленное выражение е е Е, где Е определяется рекурсивно по следующим прави- лам: двоичное представление числа и е А' есть целочисленное выражение, пред- ставляющее множество {и}; если г и I есть два целочисленных выражения, пред- ставляющие и 1., тоги / иг + /также являются целочисленными выражениями, которые представляют множества Ru Ltt {т + n: т е R, neL] соответственно. Верно ли, что к е е? 12. Система несравнимостей. Задан набор {(яь Ь\),..., (я„, 6„)} упорядоченных пар положительных чисел, в которых я; < 6, для всех /. Существует ли такое целое число х, что х = 6,(mod я,) для всех /? 13. Совместная делимость линейных многочленов. Задано 2и векторов я,=(яд, ..., а'т) и Ь, — (b'o,..., b'ln) с положительными целыми компонентами. Существуют ли такие т т положительные целые числа хь х2,..., хт, что Яр -ь^я'х, делит Ь'о + У^6'х, для ./=1 ./=1 всех 1? 14. Сравнительная делимость. Заданы две последовательности яь я2,..., я„ и bi, b2,... Ь„ положительных целых чисел. Существует ли положительное целое число с, для которого количество таких /, что с делит я„ больше числа таких j, что с делит bp 15. Точка равновесия. Заданы многочлены F{, F2, ..., F„ с целочисленными коэффи- циентами от переменных хь х2,..., х„ и конечные области определения перемен- ных ХЪХ2, ...,X„cN. Существует ли такой набор значений е -У|, у2 е Х2, ..., уп е Х„, что для всех i и всех z g X, выполнено неравенство F,(yb у2, ..., у,_ь У/+1, -,уп)^р1(у1,у2, ...,y^i,z,yi+i, ...,у„)? 16. Унификация для конечно определенных алгебр. Являются ли унифицируемыми два терма s, t g 7(S), построенные над конечной сигнатурой S заданной эквацио- нальной спецификации (S, £), где Е — множество равенств вида г = I между тер- мами r,l& T(S)?
1064 Часть III. Приложения VJ. Унификация с коммутативными операциями. Существует ли унификатор для двух заданных термов, построенных из констант и переменных с помощью ско- бок и коммутативной бинарной операции? 1.3.15. Математическое программирование 1. 0-1 целочисленное программирование. Существует ли такой /«-мерный двоичный вектору,что х-у<Ь для всех (х,6)еАи c-y>d, где А—заданное конечное множество (///+ 1)-мерных двоичных векторов, с — заданный /«-мерный двоич- ный вектор, bnd — целые числа? 2. А’-определяемость. Заданы конечное множество X пар (х,Ь). где х— некоторый /«-мерный целочисленный вектор, b — целое число, и положительное целое число к < |А]. Существует ли такое подмножество X' с X, что |.¥’| < к и для всех /«-мерных вещественных векторов у из условия х-у<Ь для всех (х,/?)еА' следует, что х • у < Ъ для всех (х, Z>) е А ? 3. Квадратичное программирование. Существует ли такой «/-мерный вектор у с ве- щественными компонентами, что х-у<Ь для всех (х.Ь)еХ и m У (с,у;2 + diyi)>r , где X— заданное конечное множество („/+ 1)-мерных веще- /=1 ственных векторов, (сь с2,..., ст) и (Jb с/2. , — заданные два /„-мерных веще- ственных вектора, Ъиг — заданные вещественные числа? 4. Линейное программирование с параметрической целевой функцией. Существует ли такой /„-мерный вещественный вектор с, что (с с)2 <q и минимум по всем m ш уеУ сумм вида У,с,у, больше, чем ^-тах|с,| + У,ггпп{0,с,} где А—заданное ,=1 ’ ./ л множество (т + 1)-мерных вещественных векторов, b и q— заданные целое и по- ложительное вещественное числа, Y— множество всех ///-мерных векторов с неот- рицательными вещественными компонентами, удовлетворяющих условию х • у > b для всех (х, Ь)<еХ 1 5. Минимальное по весу решение системы линейных уравнений. Существует ли та- кой ///-мерный вещественный вектор у , что у имеет не более заданного числа от- личных от нуля элементов и для всех (х, b) е X выполнено равенство х • у = b, где X—заданное множество (т + 1)-мерных целочисленных векторов? 6. Непрерывный рюкзак. Заданы конечное множество веществ v е V, для каждого из которых известны удельный вес s(u) е № и стоимость v(„) е М за одну единицу, разбиение V на попарно непересекающиеся подмножества V\,..., И„„ а также по- ложительные целые числа S и V. Можно ли так выбрать по одному и, из каждого
Приложение 1 РАМ, ВУ-язык и список NP-полных задач 1065 подмножества V, и так сопоставить им вещественные числа г„ что будут выпол- т т йены неравенства G И • v(p,)>K? /=1 <=| 7. Ограниченный непрерывный рюкзак. Заданы конечное множество веществ v е К, для каждого из которых известны удельный вес s(«) е М и стоимость v(i/) е TV* за одну единицу, разбиение И на попарно непересекающиеся подмножества И,Vm, каждое из которых содержит не более двух элементов, а также положи- тельные целые числа S и К Можно ли так выбрать по одному н, из каждого под- множества У, и так сопоставить им вещественные числа rh что будут выполнены т т неравенства ^r, s(p,)<S и гt i=l r=I 8. Ограниченный целочисленный рюкзак. Заданы конечное множество предметов р е Р, для каждого р из которых известен размер s(p) е а также положитель- ные числа .S' и К. Можно ли так сопоставить предметам р е Р целые числа с(д), чтобы выполнялись неравенства с(р)-s(p)<S и У с(р) • s(p) > V ? peF pel’ 9. Ограниченный частично упорядоченный рюкзак. Заданы конечное множество Р, отношение частичного порядка -< на Р, размеры s(p) е N* всех элементов р е Р,а также положительные целые числа S и К. Существует ли такое подмножество Р’ с Р, что если р е Р' и q -< р, то q е Р' и выполнены неравенства У ^(р) < Р и реР' 2>(р)>Г? реР' 10. Открытая полусфера. Заданы конечное множество /«-мерных целочисленных векторов X и положительное целое число к. Существует ли такой /и-мерный ве- щественный вектор у , что х у > 0 по крайней мере для к векторов х е X 7 11. Покомпонентные неравенства между векторами. Заданы два конечных множест- ва X и Н /и-мерных целочисленных векторов. Существует ли такой /д-мерный целочисленный вектор z, что число таких хеХ, все компоненты которых не меньше соответствующих компонент вектора z, не меньше числа векторов у е У , все компоненты которых не меньше соответствующих компонент векто- ра z ? 12. Покомпонентные неравенства между двоичными векторами. Заданы два конеч- ных множества X и Н ///-мерных двоичных векторов. Существует ли такой /д-мерный двоичный вектор z , что число таких х е X, все компоненты которых не меньше соответствующих компонент вектора z, не меньше числа векторов уеУ, все компоненты которых не меньше соответствующих компонент векто- ра z ?
1066 Часть III. Приложения 13. Рюкзак. Заданы конечное множество предметов р g Р для каждого р из которых известны размер s(p) g N* и стоимость v(p) g N\ а также положительные целые числа Sul'. Существует ли такое подмножество Р'с.Р, что у < 5 и резР1 14. Сумма размеров. Заданы конечное множество предметов р g Р, для каждого р из которых известен размер s(p) g N\ а также положительные целые числа S и И Существует ли такое подмножество Р' с Р, что У д(/?) < S и > И? реР‘ реР’ 15. Целочисленное программирование. Существует ли такой /и-мерный целочислен- ный вектор у, что х • у < b для всех (х, b) g X и с • у > d , где X— заданное ко- нечное множество (/и+1)-мерных целочисленных векторов, с — заданный т- мерный целочисленный вектор, b nd— целые числа? 16. Частично упорядоченный рюкзак. Заданы конечное множество Р, отношение частичного порядка -< на Р, размеры s(p) g N* и стоимости v(p) е N* всех эле- ментов р 6 Р, а также положительные целые числа S и V. Существует ли такое подмножество Р' cz Р, что еслир g Р' и q -< р, то q g Р' и выполнены неравенства Y,s(p)<P и ^г(р)>Г? р&р' р&р" Фиксированное линейное программирование с параметрической целевой функ- цией. Фиксировано положительное вещественное число q. Существует ли такой /и-мерный вещественный вектор с, что (с-с)2 <q и минимум по всем yeY т т сумм вида V с^у. больше, чем ymaxlc 1 + V min {0,с } , где Х~ заданное мно- — 1 тт* /=[ ./=1 жество (т + 1)-мерных вещественных векторов, b— заданное целое число, Y— множество всех /«-мерных векторов с неотрицательными вещественными компо- нентами, удовлетворяющими условию х • у > Ъ для всех (х, Ь)еХ ? 1.3.16. Теория расписаний 1. Двухпроцессорное расписание. Заданы множество заданий Q, каждому q из кото- рых приписана длительность t(q) g /V'ero выполнения и общий директивный срок Т 6 TV*. Можно ли распределить выполнение заданий Q на двух процессорах так, чтобы уложиться в директивный срок 7? 2. Минимизация веса невыполненных в срок заданий. Заданы частично упорядочен- ное множество заданий Q, для каждого задания q g Q длительность t(q) g TV* и вес w(q) g TV*, а также положительное число к. Существует ли такое однопроцессорное расписание для заданий Q, удовлетворяющее ограничениям частичного порядка,
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1067 что суммарный вес заданий, для которых нарушаются директивные сроки, не пре- вышает к? 3. Минимизация взвешенного момента окончания. Заданы множество заданий Q, число процессоров т е 7V\ для всех заданий q е Q длительности t(q) и веса w(q), а также положительное целое к. Существует ли ^-процессорное расписание заданий Q, для которого + /(<?)) w(0 к, где r{q) — время начала задания ql qeQ 4. Минимизация взвешенного момента окончания для двух процессоров Заданы множество заданий Q, длительности /(g) и веса w(q) для всех заданий q е Q, а так- же положительное целое к. Существует ли двухпроцессорное расписание заданий Q, для которого ^(г(<7) + /(g)) • и(/) < к, где r(q) — время начала задания д? get? 5. Минимизация числа заданий, не выполненных в срок. Заданы частично упорядо- ченное множество заданий Q, для каждого задания q е Q длительность /(g) е Л" и директивный срок d[cj) е TV*, а также положительное целое число к,к< |£>|. Суще- ствует ли такое однопроцессорное расписание для заданий Q, удовлетворяющее ограничениям частичного порядка, при котором нарушаются директивные сроки не более чем у к заданий? 6 Минимизация штрафа за невыполненные в срок задания. Заданы множество заданий Q, а также для каждого задания q е Q длительность /(g) е ТЛ, вес w(q) е N*, директивный срок d(q) е N' и положительное число к. Существует ли такое однопроцессорное расписание для выполнения заданий Q, что X И?)+*(?)- d<qV> w(<?) <к, где Q’— множество всех заданий, которые не вы- 4gQ полняются в срок, a r(q) — время начала задания д? 7 Многопроцессорное расписание. Заданы множество заданий Q, каждому q из ко- торых приписана длительность t(q) е М его выполнения, а также число процессо- ров т е Л/+ и общий директивный срок Т е ЛС. Можно ли распределить выполне- ние заданий Q на т процессорах так, чтобы уложиться в директивный срок 7? 8. Ограниченная минимизация числа заданий, не выполненных в срок. Заданы мно- жество заданий Q единичной длительности каждое, такой частичный порядок на Q, что каждое задание имеет не более одного непосредственно ему предшествую- щего и не более одного непосредственно следующего за ним, директивный срок d(q) е /V* для каждого задания q е Q, а также положительное целое число к, k<\Q\. Существует ли такое однопроцессорное расписание для заданий Q, удовлетво- ряющее ограничениям частичного порядка, при котором нарушаются директивные сроки не более чем у к заданий? 9. Ограниченное расписание с ограниченными ресурсами. Заданы множество зада- ний Q, длительность каждого из которых равна 1, число процессоров т е N', ди- рективный срок Т е общие размеры Р всех ресурсов и потребности в ресурсах R(q), 0 < R,(q) < Р, для всех заданий q е Q. Существует ли двухпроцессорное рас-
1068 Часть III. Приложения писание для заданий из Q, которое удовлетворяет как директивному сроку, так и ограничениям на использование ресурсов? 10. Ограниченное расписание с условиями предшествования. Заданы частично упо- рядоченное множество заданий Q, длительность каждого из которых равна 1, число процессоров m е ЛЛ. Существует ли /«-процессорное расписание для зада- ний из Г, которое имеет длительность 3 и не противоречит упорядочению зада- ний? 11. Расписание для двух процессоров с условиями предшествования. Заданы частич- но упорядоченное множество заданий Q, длительности каждого из них, равные 1 или 2, а также директивный срок Т е У4. Существует ли двухпроцессорное рас- писание для заданий из Т, которое удовлетворяет директивному сроку и не про- тиворечит упорядочению заданий? 12. Расписание для случая одного процессора. Задано множество заданий q е Q, а также для каждого q е Q длительность г(<у), момент его поступления г(д) и дирек- тивный срок d(q). Существует ли однопроцессорное расписание выполнения за- даний Q, согласованное с моментами поступления заданий и их директивными сроками? 13. Расписание с индивидуальными директивными сроками. Заданы частично упоря- доченное множество заданий Q, каждое из которых имеет длительность 1, число процессоров те а также индивидуальные директивные сроки d(q) для всех заданий q е Q. Существует ли /«-процессорное расписание заданий, которое удовлетворяет как условиям предшествования, так и всем директивным срокам? 14. Расписание с ограниченными ресурсами. Заданы множество заданий Q, длитель- ность каждого из которых равна 1, число процессоров m е /V4, директивный срок Т е JV4, число видов ресурсов /• е ТУ4, а также для каждого /, 1 <1<г, общие раз- меры Pi всех ресурсов номера i и потребности в ресурсах R, (q), 0 < Rt(q) < Р, для всех заданий q е Q. Существует ли /«-процессорное расписание для заданий из Q, которое удовлетворяет как директивному сроку, так и ограничениям на исполь- зование ресурсов? 15. Расписание с прерываниями. Заданы частично упорядоченное множество зада- ний Q, число процессоров, длительности t(q) всех заданий q е Q и общий дирек- тивный срок Т е ТУ4 Существует ли такое /«-процессорное расписание для зада- ний из Q, допускающее прерывания заданий, которое удовлетворяет как услови- ям предшествования, так и общему директивному сроку? 16. Расписание с условиями предшествования. Заданы частично упорядоченное множество заданий Q, длительность каждого из которых равна 1, число процес- соров m е /V4, директивный срок Т е N*. Существует ли ///-процессорное распи- сание для заданий из Q, которое удовлетворяет директивному сроку и не проти- воречит упорядочению заданий? 17. Учебное расписание. Заданы множества рабочих часов Н, преподавателей С, учебных дисциплин Т, а также для всех с е С и t е Т подмножества допустимых
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1069 часов А(с), A(t) с/' и требуемая нагрузка /?(с, Z) е No- Существует ли учебное расписание /:Сх Ух//-> {О, I}, удовлетворяющее следующим свойствам: /(с, Z, Л)=1 тогда и только тогда, когда h е А(с) гл A(t\, для каждого h е Н и с е С существует не более одного t g Т такого, что f{c, t, h) = 1; для каждого h g Н и Z е Т существует не более одного с g С такого, что Дс, Z, А) = 1; для каждой па- ры (с, I) е С х Т существует ровно R(c, f) значений И, для которых/(с, t,h)= 1? 1.3.17. Разные задачи 1. Декодирование линейных кодов. Заданы двоичная матрица А = (а,,) размера m х /?, двоичный вектор у = и положительное целое число к. Существует ли такой двоичный вектор х = (л, ,...,х„), имеющий не более к отличных от нуля эле- п ментов, что =yz(mod 2) для всех/? i=i 2. Дерево решений. Заданы конечное множество объектов X, набор предикатов Т={Т\, Тг,..., Т„}, заданных на X, т. е. Т,:Х—>{0,}, положительное целое число к. Существует ли для X дерево решений с использованием Т, в котором сумма длин путей от корня до листьев не превышает к? 3. Достижимость в консервативных сетях Петри. Верно ли, что в заданной консерва- тивной сети Петри из начальной разметки достижима заданная разметка? 4. Живость сетей Петри со свободой выбора. Верно ли, что не обладает свойством живости заданная сеть Петри, в которой у каждого перехода либо одно входное место, либо несколько таких, которые являются входными только для данного пе- рехода? 5. Логический подграф. Заданы орграф G=(V, А), имеющий ровно одну вершину р0 без заходящих дуг, веса и>(е) для всех дуг е g А, значение ftp) е {and, or} для всех таких р, из которых есть исходящие дуги, целое положительное число к. Сущест- вует ли в G такой подграф С = (К', А1), что справедливы следующие четыре свой- ства: р0 g У; если р g У и Др) = and, то все дуги, исходящие из р в G, содержатся в Л'; если р g V' и Др) = or, то по крайней мере одна из дуг, исходящих из р в G, содержится в А'; сумма весов дуг из А 'не превосходит кУ. 6. Ограниченные скопления. Заданы конечное множество X, расстояния d(x,y) g N^, О < d(x,y) < 1, для каждой пары х,у g X и два положительных целых числа К и D. Существует ли такое разбиение X на три попарно непересекающиеся подмножест- ва Х\, Х2 Х3, что для всех / и всехх, у g X, расстояние d(x, у) не превышает £>? 7. Представимость конечной функции. Заданы конечное множество А, семейство F функций /: Л —>Л и выделенная функция h : Л —> А. Может ли функция h быть представлена в виде композиции функций из F? 8. Ранжирование по максимуму правдоподобия. Заданы целочисленная матрица Л = (а,,) размером п х и, для которой а;/ + a,, = О для всех z и j, и положительное
1070 Часть III. Приложения целое число с. Существует ли матрица В = (by), которую можно получить из А одновременной перестановкой строк и столбцов, такая, что min {by ,0} > - с? is«y<« 9 Скопления. Заданы конечное множество X, расстояния d(x, у) е для каждой пары х, у е X и два положительных целых числа К и D. Существует ли такое раз- биение X на попарно непересекающиеся подмножества А), У2, —,Ль что для всех i и всех х, у е X, расстояние d(x, у) не превышает Z?? 10. Соотношение "между". Заданы конечное множество X и набор троек (а, Ь, с) раз- личных элементов из X. Существует ли такая нумерация F элементов из X, что для любой тройки (а, Ь, с) либо F(a) < F(b) < F(c), либо F(c) < F(h) < F(dft 11. Тест случайности для пар. Заданы последовательность (хь _У1), (х2, у2), —, (х„, у„) упорядоченных пар целых чисел, неотрицательное целое число к. Существуют ли не менее к подмножеств Sc{l,2,...,«}, для каждого из которых ieS у, <х{ 12. Циклическое упорядочение. Заданы конечное множество X, набор С упорядочен- ных троек (а, Ь, с) различных элементов из X. Существует ли такая нумерация F элементов из X, что для каждой тройки (a, b,c) е С выполнено одно из свойств: F(a) < F(b) < F(c), либо F(/>) < F(c) < F(a), либо F(c) < F(a) < F(b)? Библиографический комментарий Исследования моделей вычислений — это важное и хорошо развитое направление математики, знакомство с результатами которого можно начать с книг [25, 30] и обзора [23]. Вопросы су- ществования вычислимых методов или алгоритмической неразрешимости с энциклопедиче- ской полнотой изложены в [22], а книга [24] является общедоступным введением в теорию алгоритмов. Использование РАМ для анализа алгоритмов получило широкое распространение с 70-х гг. В работах, посвященных анализу сложности конкретных задач и алгоритмов, в терминах опе- раций для РАМ становится нормой применение нсевдоязыка (лексикона) программирования, допускающего использование традиционных конструкций математики и языков программиро- вания. Первая систематическая реализация этого подхода проводится в [1], где с единых пози- ций излагаются результаты построения и анализа алгоритмов для разных задач, включая зада- чи на графах и задачи реализации сложных структур данных (там же можно почерпнуть до- полнительные сведения о РАМ и ее связи с другими моделями вычислений). ВУ-язык использовался нами в книгах [7—9] и заимствован из монографии [12]. В книге [25] дается обзор важнейших идей и работ в области теории алгоритмов. Излагаются в систематизированном виде основные открытия, связанные с понятием алгоритма, приложе- ния теории алгоритмов к математической логике, теории вероятностей, теории информации и др. Рассматривается влияние теории алгоритмов на алгоритмическую практику.
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1071 Статья [23] — это обзор основных понятий и результатов собственно теории сложности вы- числений, а также некоторых результатов по анализу сложности конкретных задач. Она со- держит представительную библиографию (около 400 наименований) и уделяет значительное внимание вопросам, представляющим интерес не только для теории сложности вычислений, но и для различных разделов математики, имеющих дело с разработкой и анализом алгорит- мов. Вопросам формализованного сложностного анализа и эффективизании программных исследо- ваний свойств алгоритмов и структур данных посвящена книга [16]. В ней описание общей методики иллюстрируется на примере алгоритмов над деревьями. Работа [21] обращена к читателю, который интересуется комбинаторными алгоритмами в силу их практического значения. В ней предпринята довольно успешная попытка систематизации комбинаторных алгоритмов, выявления их общих черт и закономерностей. Рассматриваются вопросы представления и порождения комбинаторных объектов, их подсчета и оценивания, исчерпывающего и быстрого поиска, сортировки, обработки графов и др. Авторы старались выделить практически важные аспекты комбинаторных алгоритмов и опустить детали, кото- рые может восполнить любой квалифицированный программист. Монография [5] посвящена общим принципам решения задач на ЭВМ, разработке и анализу алгоритмов. Несомненным достоинством является то, что при сравнительно небольшом объе- ме она покрывает обширный фактический материал (в том числе и генераторы случайных чи- сел) и может помочь в первоначальном знакомстве с предметом, подробно изложенным в мо- нографиях [1, 15, 17] Методам представления сложноорганизованных данных в памяти вычислительной машины и создания программ со сложными структурами данных посвящены книги [2—4, 14—17, 19]. Класс Р был определен в 1964 г. Кобэмом [27] и независимо в 1965 г. Эдмондсом [29]. Эд- мондс определил также класс NP и высказал гипотезу, что Р NP. В 1971 г. Кук [18, 28] ввел понятие АР-полноты и доказал, что задача о выполнимости логических формул является АР- полной. Независимо определение АР-полноты было рассмотрено А. А. Левиным [20], который доказал АР-полноту некоторых задач. Карп в 1972 г. предложил метод сведения за полиноми- альное время и использовал его для доказательства АР-полноты целого ряда задач [11, 31], среди которых задачи о клике, вершинном покрытии и гамильтоновом цикле. К настоящему времени благодаря усилиям многих ученых известны сотни АР-полных задач. Прекрасным введением в теорию АР-полноты является книга Гэри и Джонсона [6], которая содержит большой список АР-полных задач, существенно использованный нами при подго- товке данного приложения. Эта книга может служить как учебником для читателя, интере- сующегося теорией труднорешаемых задач, так и справочником для исследователя и практика, сталкивающегося с алгоритмами и их сложностью. В ней приведены точные формулировки большого числа АР-полных задач (из самых разнообразных областей), для каждой из которых, помимо основной формулировки и источника, приводится комментарий, включающий сводку результатов о задаче и ее модификациях (с указанием авторов), а также обсуждение смежных вопросов. Подробное обсуждение АР-полноты и смежных разделов теории сложности вычислений мож- но найти в книгах [1, 13, 17] и обзорах [23, 26]. Значение многих терминов, использованных в формулировках задач, может быть найдено в |Ю].
1072 Часть III. Приложения Список литературы 1. Ахо А., Хопкрофт Дж., Ульман Дж. Построение и анализ вычислительных алгоритмов. — М.: Мир, 1978. 2. Ахо А., Хопкрофт Дж., Ульман Дж. Структуры данных и алгоритмы.— М.: Вильямс, 2001. 3. Берзтисс А. Т. Структуры данных. — М.: Статистика, 1974 4. Вирт Н. Алгоритмы + структуры данных = программы. — М.: Мир, 1985. 5. Гудман С., Хидетниеми С. Введение в разработку и анализ алгоритмов. — М.: Мир, 1981. 6. Гэри М., Джонсон Д. Вычислительные машины и труднорешаемые задачи.— М.: Мир, 1982. 7. Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки деревьев. — Ново- сибирск: Наука, 1994. 8. Евстигнеев В. А., Касьянов В. Н. Теория графов: алгоритмы обработки бесконтурных графов. —Новосибирск: Наука, 1998 9. Евстигнеев В. А., Касьянов В. Н. Сводимые графы и граф-модели в программировании. — Новосибирск: ИДМИ, 1999. 10. Евстигнеев В. А., Касьянов В. Н. Толковый словарь по теории графов в информатике и в программировании. — Новосибирск: Наука, 1999. 11. Карп Р. М. Сводимость комбинаторных задач // Киб. сб. — М.: Мир, 1975. — С. 16—38. 12. Касьянов В. Н. Оптимизирующие преобразования программ. — М.: Наука, 1988. 13. Касьянов В. Н. Лекции по теории формальных языков, автоматов и сложности вычисле- ния. — Новосибирск: НГУ, 1995. 14. Касьянов В. Н., Сабельфельд В.К. Сборник заданий по практикуму на ЭВМ. М.: Наука, 1986. 15. КнутД. Искусство программирования для ЭВМ.— М.: Мир, 1976.— Т. 1. Основные алгоритмы. 16. Кожевникова Г. П. Структуры данных и проектирование эффективной вычислительной среды. — Львов: Вища шк., 1986. 17. Кормен Т., Лейдерсон Ч., Ривест Р. Алгоритмы: построение и анализ.— М.: МЦНМО. 2001. 18. Кук С. А. Сложность процедур вывода теорем. // Киб. сб. Нов. сер. — 1975. — Вып. 12. — С. 5—15. 19. Лавров С. С., Гончарова Л. И. Автоматическая обработка данных, хранение информации в памяти ЭВМ. — М.: Наука, 1971. 20. Левин А. А. Универсальные задачи перебора И Проблемы передачи информации. — 1973. —Т. 9, №3 —С. 115—116. 21. Рейнгольд Э., Нивергельт Ю., Део Н. Комбинаторные алгоритмы: теория и практика.— М.: Мир, 1980. 22. Роджерс X. Теория рекурсивных функций и эффективная вычислимость. — М.: Мир, 1972.
Приложение 1. РАМ, ВУ-язык и список NP-полных задач 1073 23. Слисенко А. О. Сложностные задачи теории вычислений // Успехи мат. наук. — 1981. — Т. 36. N 6. —С. 21—103. 24. 'Грахтенброт Б. А. Алгоритмы и вычислительные автоматы. -— М.: Сов. Радио, 1974. 25. Успенский В. А., Семенов А. Л. Теория алгоритмов: основные открытия и приложения. — М.: Наука, 1987. 26. Хартманис Дж„ Стирнз Р. О вычислительной сложности алгоритмов // Киб. сб. Нов. сер. — 1967. — Вып. 4. — С. 57—85. 27. Cobham A. The intrinsic computational difficulty of functions // Proc. 1964 International Con- gress for Logic Methodology and Philosophy of Science. — North Holland, Amsterdam, 1964, —P. 24—30. 28. Cook S. A. The complexity of theorem-proving procedures // Proc. 3rd Ann. ACM Symp. on Theory of Computing. — Association for Computing Machinery, New York, 1971. 29. Edmonds J. Paths, trees, and flowers // Canad. J. Math. — 1965. — Vol. 17. — P. 449—467. 30. Handbook of Theoretical Computer Science — Elsevier Science Publ., 1990.— Vol. A, B. 31. Karp R, M. Reducibility among combinatorial problems // Complexity of Comput. Computa- tions. — Plenum Press, New York, 1972. — P. 85—103. I 35 Зак. 202
ПРИЛОЖЕНИЕ 2 Характеристики размещений графов Известные методы и задачи рисования графа можно сопоставить, рассмотрев их эсте- тические и сложностные характеристики. Во многих случаях эти характеристики не являются независимыми, и разработчику алгоритмов рисования графов требуется уметь находить компромисс между различными эстетическими свойствами размеще- ния графов, а также между эстетическими характеристиками изображения графа и сложностью его построения. Данное приложение содержит справочный материал по известным верхним и нижним оценкам свойств различных размещений графов, а также рассматривает некоторые связи между ними. При этом рассматриваются как (универсальные) верхние оценки, справедливые для всех графов изучаемого класса, так и существенные оценки в каче- стве низших, которые справедливы для бесконечного числа графов класс и означают, что имеется бесконечное множество графов, которые превышаю! указанные нижние границы. В разд. 2.1—2.3 данного приложения приводятся оценки размера области размеще- ния графов, величины углов и числа сгибов соответственно. Разд. 2.4 посвящен во- просам взаимосвязи между указанными характеристиками, в разд. 2 5 обсуждаются вопросы сложности алгоритмов и задач рисования графов. Через п и т обозначаются количества вершин и ребер изображаемого графа 2.1. Размер области размещения Приведенные в данном приложении оценки размера области размещения предпола- гают, что имеются определенные границы разрешения, которые не позволяют при рисовании графа произвольно уменьшать масштаб его размещения на плоскости. В частности, эти границы могут выражаться либо в задании некоторого минималь- ного расстояния, ближе которого нельзя размещать вершины друг от друга, либо в требовании к расположению вершин и точек пересечения ребер графа в узлах неко- торой заданной сетки, так называемое сетчатое изображение графа. При рассмотрении оценок размеров областей размещения графов следует также иметь в виду следующие свойства изображений графов. Сгибы ребер двояким обра-
Приложение 2. Характеристики размещений графов 1075 зом влияют на размер области размещения графа. С одной стороны, они занимают определенное место и, следовательно, иногда могут приводить к увеличению размера области размещения. С другой стороны, использование сгибов позволяет в некоторых случаях провести ребра без увеличения области размещения. Линейные (или почти линейные) границы размера области размещения можно дос- тичь при рисовании деревьев. Связь между размерами области размещения и величи- нами углов разрешения при рисовании деревьев представлена в разд. 2.4.2 этого при- ложения. Планарные графы можно разместить в области квадратичного размера. Однако для случая прямолинейного изображения планарного графа может потребоваться область экспоненциального размера, если задано высокое угловое разрешение, требуемое при рисовании графа. Вместе с тем, если не требовать, чтобы размещение графа было бы плоским, то можно нарисовать планарный граф в области почти линейного размера. Имеется интересная связь у восходящего планарного размещения графа между раз- мером области,' занимаемой графом, и общим числом сгибов его ребер. Когда орграф сводим, размер области его прямолинейного размещения является экспоненциальным в худшем случае. Однако некоторую квадратичную границу размера области его раз- мещения можно достичь, использовав лишь линейное число сгибов. 2.1.1. Деревья В приведенных в данном приложении оценках размеров областей, необходимых для расположения деревьев, п обозначает число его вершин, з к— произвольную кон- станту из отрезка [0,1). Корневые деревья Обычно применяемый метод [73] для строго нисходящих планарных прямолинейных сохраняющих вложение размещений корневых деревьев имеет для размера области верхнюю оценку и существенно нижнюю Q(hz). Метод нисходящего плоского сетча- того расположения корневых деревьев [19, 77] позволяет нарисовать их в области размера О(п log и), но уже может не сохранять порядок сыновей вершин. Если вер- шины корневого дерева имеют степень 0(1), то их нисходящее плоское сетчатое прямолинейное расположение в области размера О(п log log ri) может быть осуществ- лено методом, описанным в [78]. Полилинейное нисходящее плоское сетчатое сохра- няющее вложение расположение графа [45] имеет верхней оценкой О(п log ri) и су- щественно нижней Q(h log ri), но не всегда дает наглядные рисунки дерева. Бинарные деревья Методы //v-рисования [19, 77] и рекурсивного спуска [13] строят нисходящие плоские сетчатые ортогональные изображения бинарных деревьев в области, размер которой имеет верхнюю оценку О(п log ri) и существенную нижнюю Cl(ri). Для полных де- ревьев, АВЛ-деревьев и Фибоначчиевых деревьев метод нисходящего плоского сет- чатого прямолинейного изображения [20, 86] требует области размера с верхней оценкой О(п) и существенной нижней Q(h).
1076 Часть III. Приложения Деревья Плоское праволинейное сетчатое изображение дерева [19, 77] занимает область, верхняя граница размера которой О(п log и), а существенная нижняя — Q(n). Метод планарного полилинейного сетчатого изображения [45] позволяет размещать деревья со степенью вершин О(пк) в области размера О(п). Такая же оценка [59, 89] справед- лива для размера плоского ортогонального сетчатого изображения дерева, вершины которого имеют степень 4. Взаимосвязи между размером области размещения и величиной углового разрешения рассматривается в разд. 2.4 данного приложения. 2.1.2. Планарные графы Плоские изображения Существует целый ряд методов, позволяющих плоские изображения планарных гра- фов в области размера О(п'), причем эта оценка достижима. Среди них различные методы полилинейного сетчатого размещения [26, 28, 55], основанные на ориентаци- ях и нумерациях, методы ортогонального сетчатого размещения [7, 25, 46, 54, 81, 83], основанные на ориентациях, нумерациях и потоках в сети, методы полусетчатого размещения [74, 82], методы плоского сохраняющего вложение полилинейного сет- чатого изображения [26, 28, 55], методы плоского сохраняющего вложение прямоли- нейного сетчатого изображения [21, 76], а также метод сохраняющего вложение плоского сетчатого прямолинейного выпуклого изображения [55]. Неплоские изображения Имеется несколько методов [5, 59, 89], позволяющих строить неплоские ортогональ- ные изображения планарных графов степени 4 в области размера О{п log- п). Для та- ких изображений известна [58] существенная нижняя оценка размера £2(и log и). Восходящие плоские изображения Такие изображения применяются для планарных орграфов. Справедливы верхняя оценка О(п2) и существенная нижняя оценка Q(n2) для размеров мозаичного и види- мого расположений «-графов с целочисленными координатами [74, 82, 84]. Те же (квадратичные) оценки имеют место для плоского восходящего сетчатого прямоли- нейного сохраняющего вложение изображения редуцированного планарного .«-графа [28], плоского восходящего сетчатого полилинейного изображения восходящего пла- нарного орграфа [26, 28], а также плоского восходящего сетчатого прямолинейного изображения последовательно-параллельного графа [3, 47]. Экспоненциальные оценки О(с") и Q(Z>") размера области известны для плоского вос- ходящего планарного орграфа [3, 47], а также плоского восходящего сохраняющего вложение прямолинейного изображения последовательно-параллельного орграфа [3].
Приложение 2. Характеристики размещений графов 1077 2.1.3. Графы общего вида Методы, основанные на ориентации [7, 71, 89], требуют для ортогонального сетчато- го изображения графа, степень вершин которого не превышает 4, такой области на плоскости, размер которой имеет верхнюю границу О(и2) и существенную нижнюю П(и2). Для того чтобы нарисовать на плоскости произвольный граф, можно сначала привес- ти его планарному виду пут&м добавления вершин, являющихся пересечением ребер, потом применить один из квадратичных методов для рисования планарных графов, а затем удалить добавленные ранее вершины. В результате мы получаем алгоритм, по- зволяющий изобразить произвольный граф в области размера О((п + А)2), где к — число пересечений р'-бер, ставших вершинами. Заметим, что проблема нахождения минимального числ i вершин, которые нужно добавить для приведения графа к пла- нарному виду, является Л'/’-трудной. Существуют методы [9, 68, 72], позволяющие для графа с m ребрами строить ортого- нальное сетчатое изображение размера О(/и2). 2.2. Оценка величины углов Для графов общего вида тривиальной верхней оценкой углового разрешения является число 2л/d, где d— максимальная степень вершин графа. Отсюда следует достиЖи- мая вер?<няя граница 0(1/п). Размещая все вершины графа в вершинах правильного и-угольника, получаем тривиальную нижнюю оценку Q(l/n). Метод раскраски [40] может быть использован для доказательства следующих ниж- них границ для углового разрешения праволинейных (неплоских) расположений: Qfl/’d2) для графов общего вида и 0(1/<Д для планарных графов. Дл;я плоских праволинейных изображений оценка 0(1 /и") углового разрешения дос- тигается на любом плоском прямолинейном сетчатом изображении высоты О(п) и Ширины О(п), как оно строится алгоритмами, описанными в [21, 76]. С другой сторо- /ны, наилучшая известная нижняя граница углового разрешения в зависимости только от d является £2( 11с\ где с, с > 1, обозначает некоторую константу [64]. Оптимальные полилинейные изображения могут достигать углового разрешения Q( 1/d) [55]. Взаимосвязь между размером области размещения и величиной углового разрешения рассматривается в разд. 2.4 данного приложения. 2.3. Число сгибов Все верхние границы для числа сгибов, получаемых алгоритмами рисования с ис- пользованием нумерации и ориентации, являются достижимыми [7, 9, 38, 55, 63, 68— 72, 83]. Нижние границы числа сгибов обсуждаются в работах [6] и [85]. Можно построить ортогональное изображение графа, в котором будет не более одно- го сгиба на ребро [72]. Если же степень вершин не превышает 4, то можно строить
1078 Часть III. Приложения изображения, в которых не больше 2 сгибов на ребро, а суммарно число сгибов не более 2п + 2 и не менее (11/6)и [6, 7, 70, 71]. Планарные графы Для планарных графов с максимальной степенью вершин 4 методы [7, 72] позволяют строить ортогональные плоские изображения, в которых не более 2 сгибов у ребра и суммарно не менее 2m + 2 и не более 2п — 2 сгибов у всех ребер, а методы [38, 62, 72, 83]— ортогональные плоские сохраняющие вложения изображения, в которых у каждого ребра не более 3 сгибов, а всего (у всех ребер)- не менее 2п — 2 и не более 12/5и + 2 сгибов. Для бисвязных планарных графов с максимальной степенью вершин 4 существует ряд методов [38, 62, 72, 83] построения ортогональных плоских сохраняющих вложе- ние изображений, в которых каждое ребро имеет не более трех ci чбов, а всего сгибов не менее 2п - 2 и не более 2п + 2. Трехсвязные планарные графы с максимальной степенью вершин 4 можно [55] пред- ставить в виде ортогональных плоских сохраняющих вложений изображений, каж- дое ребро которых имеет не более двух сгибов, а суммарно у всех ребер не менее 4/3 (и - 1) + 2 и не более 3/2» + 4 сгибов. > Для планарных графов с максимальной степенью вершин 3 методы [55, с52] позволя- ют строить ортогональные плоские сохраняющие вложения изображения'; суммарно имеющие ровно 1/2 п + 1 сгибов и содержащие не более одного сгиба у любого ребра. 2.4. Связь разных характеристик Разнообразные взаимовлияния между размером и отношением сторон возникают ,при рисовании даже графов простой структуры, таких как, например, деревья. 2.4.1. Связь между размером и отношением сторон при изображении деревьев Для корневых деревьев поуровневое (восходящее плоское прямолинейное) сетчатое изображение можно осуществить в области размера О(и2) и с отношением сторон 0(1) [73], а также в области размера О(п log и) с отношением сторон O(nAog, ri) [19, 77]. Для бинарных деревьев известны методы построения: П восходящего плоского прямолинейного ортогонального сетчатого изображения в области размера <Xl°g log п) с отношением сторон 0(1) [13]; П восходящего плоского ортогонального сетчатого изображения в области размера O(Iog log п) с отношением сторон О((и log log ri)/ log2 n) [45]; П плоского прямоугольного ортогонального сетчатого изображения в области раз- мера О(п log ri) с отношением сторон 0(1) [13].
Приложение 2. Характеристики размещений графов 1079 Корневые деревья со степенью вершин О(и“), где 0 < a < 1 можно представить в виде восходящего плоского ортогонального сетчатого изображения в области размера О(п) с отношением сторон О(и“) [45]. Для деревьев с максимальной степенью вершин 4 есть методы [59, 89] построения плоских ортогональных сетчатых изображений в области размера O(ri) с отношением сторон 0(1). 2.4.2. Связь между размером области и величины углового разрешения для планарных графов Для планарных графов существуют методы: построения прямолинейных изображе- ний в области размера O(J6n) и с угловым разрешением Q(l/<72) [40], а также в облас- ти размера О(<73 ri) с угловым разрешением Q(l/J) [40]; построения плоских прямоли- нейных изображений сетчатых изображений в области размера О(и2) с угловым раз- решением Q(l/n2) [21, 76]; построения плоских прямолинейных изображений в области размера £1(<?п) с угловым разрешением П(р) [48], а также в области размером О(Ь") с угловым разрешением Q(l/cJ), где b,b> 1, и с, с> 1 — некоторые константы [64]; построения плоских полилинейных сетчатых изображений в области размера О(п2) и угловым разрешением Q(l/J) [55]. Для планарных графов со степенью вершин 0(1) известны плоские прямолинейные изображения в области размера Q(c") и угловым разрешением Q(l) [48, 64]. 2.5. Вычислительная сложность 2.5.1. Проверка планарности и вложения Проблема минимизации пересечений при рисовании графов является Л'Р-трудной [42]. Проблема минимизации пересечений в поуровневом изображении при изобра- жении двухуровневого графа с предопределенным порядком на одном уровне являет- ся ^-трудной [36]. Проблема выявления максимального по числу вершин планарного подграфа в графе является УУР-труд ной [41]. Задача проверки планарности и вычисления планарного расположения имеет времен- ную сложность 6(и) [10, 14, 22, 39, 52, 60]. Задача нахождения в заданном графе максимального (по включению) планарного подграфа имеет временную сложность 0(и + т) [12, 27, 30,49, 57]. Задача проверки, имеет ли заданный орграф восходящее плоское изображение, явля- ется ^-трудной [49]. Нижняя оценка Q(n) и верхняя О(и2) справедливы для временной сложности провер- ки существования восходящего плоского изображения как для вложенного орграфа [1], так и для внешнепланарного орграфа [67].
1080 Часть III. Приложения Временная сложность 0(л?) справедлива для проверки существования восходящего плоского изображения как для вложенного внешнепланарного орграфа [67], так и для орграфа с одним источником [2, 53]. 2.5.2. Прямолинейные и полилинейные изображения планарных графов Задача построения для планарного 1рафа его плоского прямолинейного изображения с заданными длинами ребер является ^-трудной [37]. Задача построения для вложенного планарного графа его плоского прямолинейного изображения с заданными углами является МР-трудной [43]. Задача построения для планарного графа его плоского прямолинейного изображения с максимальным угловым разрешением является ЛР-трудной [43, 55]. Задача построения для максимального планарного графа его плоского прямолинейно- го изображения с заданными углами имеет временную сложность О (и) [30]. Временную сложность О(п) имеют задачи построения для заданного планарного гра- фа: его плоского прямолинейного сетчатого изображения в области размера О(п2) и угловым разрешением Q(l/n~) [18, 21, 76]; его плоского полилинейного сетчатого изображения в области размера О(п2) числом изгибов (9(и) и угловым разрешением 0(1/<7) [55]; его наглядного представления в области размера О(п2) [26, 29, 54, 74, 82]. Временную сложность О(п) имеют задачи построения для заданного трехсвязанного планарного графа его плоского прямолинейного выпуклого сетчатого изображения в области размера О(п2) и с угловым разрешением С1(1/л2) [55], а также его плоского прямолинейного строго выпуклого изображения [15, 87, 88]. Задача построения для внешнепланарного графа его плоского прямолинейного сим- метричного изображения имеет временную сложность <9(и) [66]. Задача построения для редуцированного планарного л/-графа его восходящего плос- кого сетчатого прямолинейного доминантного изображения в области минимального размера имеет временную сложность О(п) [28]. Задача построения для восходящего планарного орграфа его восходящего плоского полилинейного сетчатого изображения в области размера О(н2) и числом изгибов О(п) имеет временную сложность О(п) [26, 28]. 2.5.3. Изображения графов с заданной степенью вершин Пусть А обозначает класс всех графов с максимальной степенью верцшн, не превы- шающей 4. Задача построения по графу G е А его ортогонального сетчатого изображения в об- ласти размера О(и2) и с числом изгибов О(п) имеет временную сложность 0(и) [7, 69—71].
Приложение 2. Характеристики размещений графов 1081 Задача построения по планарному графу G е А его плоского ортогонального сетчато- го изображения в области размера О(п2) и с числом изгибов О(п) имеет линейную временную сложность 6(и) [7, 54, 83]. Задача построения для планарного графа G е А его плоского ортогонального сетча- того изображения с минимальным числом изгибов является Л'Р-трудной [49]. Задача построения для планарного графа с максимальной степенью вершин, мень- шей 3, его плоского ортогонального сетчатого изображения с минимальным числом изгибов и в области размера О(п2у) требует не менее <Э(и) времени и может быть ре- шена за время ()(п log и) [25]. Задача построения по вложенному планарному графу G е А его плоского ортого- нального сетчатого изображения с минимальным числом изгибов и в области размера (Х”2) требует не менее Q(h) времени и может быть решена за время Л log и) [47,81]. 2.5.4. Рисование деревьев Полиномиальный алгоритм, основанный на методах линейного программирования, минимизирует размер области плоского прямолинейного восходящего поуровневого размещения дерева, демонстрирующего симметричность и изоморфизм поддеревьев [80]. Однако изображение, конструируемое этим алгоритмом, в общем случае не является сетчатым расположением. Минимизация размера области M -изображения бинарных деревьев также может быть осуществлена полиномиальным алгоритмом, основанном на методах линейного про- граммирования [34]. Многие другие задачи оптимизации размещения графов являются А'Р-трудными, в том числе задачи: изображения дерева в качестве минимального покрывающего дерева для заданного множества точек на плоскости [35]; минимизации размера плоского ортогонального сетчатого изображения дерева степени 4 [11, 31, 56, 79]; минимизации суммарной длины ребер или максимальной длины ребра плоского орто- гонального сетчатого изображения дерева степени 4 [4, II, 51]; минимизации размера области плоского прямолинейного восходящего поуровневого сетчатого размещения корневых деревьев, демонстрирующего симметрию и изоморфизм поддеревьев [80]. Эффективные алгоритмы рисования, которые гарантируют справедливость хороших верхних оценок размера области размещения, известны для корневых и бинарных деревьев. Бинарные деревья можно разместить в области минимального размера за время, не меньшее Q(n) и не превышающее О(п (и log л)1/2) [34]. Размещение корневого дерева в области минимального размера при построении плоского прямоугольного восходящего поуровневого изображения, демонстрирую- щего симметрию и изоморфизм поддеревьев, может быть осуществлено с временной сложностью О(пк) методом, требующим не менее Q(n) времени [80].
1082 Часть III. Приложения Для корневых деревьев существуют эффективные алгоритмы с временной слож- ностью 6(и) для задач построения плоского прямолинейного восходящего поуровне- вого сетчатого изображения в области размера О(и2) [73], плоского полилинейного восходящего сетчатого изображения в области размера О(п) [44], плоского прямоли- нейного восходящего сетчатого изображения в области размера О(п log и) [13, 19, 77]. Библиографический комментарий Вопросы рисования графов достаточно подробно рассматривались нами в гл. 5; где читатель может найти обширную аннотированную библиографию по этим вопросам. Поэтому здесь мы ограничиваемся ссылками только на те работы, которые непосредственно связаны с характери- стиками размещений графа, рассмотренными в данном приложении. Для более глубокого зна- комства с существующими характеристиками задач и известных методов размещения графов отсылаем читателя к книгам [23, 33] и обзорным статьям [24, 90], существенно использован- ных нами при подготовке данного приложения. Заметим, что в обзоре [24] приводятся харак- теристики размещения графов не только на плоскости, но и в пространстве, а обзор [90] дает обзор характеристик не только изображений графов, но и других их представлений, таких, как, например, матрица или списочная структура. Список литературы 1. Bertolazzi Р., Di Battista G., Liotta G., Mannino C. Upward drawings of triconnected digraphs // Algorithmica. — 1994. — Vol. 6, N 12. — P. 476—497. 2 Bertolazzi P., Di Battista G.,Mannino C., 1'amassia R. Optimal upward planarity testing of sin- gle-source digraphs//SIAM J. Comput.— 1998. — Vol. 27, N 1.—P. 132—169. 3. Bertolazzi P.,Cohen R.F., Di Battista G.. Tamassia R.,Tollis I.G. How to draw a series-parallel digraph // Int.J. Comput. Geom. Appl. — 1994. — Vol. 4. — P. 385—402. 4. Bhatt S., Cosmadakis S. The complexity of minimizing wire lengths in VLSI layouts// Inform. Process. Lett. — 1987. — Vol. 25. — P. 263—267. 5. Bhatt S. N., Leighton F.T. A framework for solving VLSI graph layout problems // J. Comput. Syst. Sci. — 1984. — Vol. 28. — P. 300—343 6. Biedl T. New Lower bounds for orthogonal graph drawings // Leet. Notes in Comp. Sci. — 1996.—Vol. 1027, —P. 2a—39. 7 Biedl T., Kant G. A better heuristic for orthogonal graph drawings// Leet. Notes Comput. Sci. — 1994. — Vol. 855. — P. 24—35. 8. Biedl T., Kaufmann M. Area-efficient static and incremental graph drawings // Leet. Notes Comput. Sci. — 1997. — Vol. 1284. — P. 37—52. 9. Biedl T.C. Orthogonal Graph Visualization: The Three-Phase Method With Applications.— PhD thesis, RUTCOR, Rutgers University, May 1997. 10. Booth K., Lueker G. Testing for the Consecutive Ones Property Interval Graphs and Graph Pla- narity Using PQ-Tree Algorithms // J. Comput. Syst. Sci. — 1976. — Vol. 13. — P. 335—379. 11 Brandenburg F. J. Nice Drawings of Graphs and Trees are Computationally Hard. —Technical Report MIP-8820. Fakultat fur Mathematik und Informatik. Univ. Passau, 1988.
Приложение 2. Характеристики размещений графов 1083 12. Cai J., Han X., Tarjan R. E. An O(m log n)-time algorithm for the maximal subgraph problem // SIAM J. Comput.-- 1993, — Vol. 22. — P. 1142 1162. 13. Chan T., Goodrich M. T„ Kosaraju S. R., Tamassia R. Optimizing area and aspect ratio in straight-line orthogonal tree drawings// Leet. Notes Comput. Sci.— 1997.— Vol. 1190.— P 63 -75. 14. Chiba N., Nishizeki T.. Abe S.. Ozawa T. A linear algorithm for embedding planar graphs using PQ-Trees //J. Comput. Syst. Sci. — 1985. — Vol. 30, N 1. — P. 54—76. 15. Chiba N., Onoguchi K_, Nishizeki T. Drawing planar graphs nicely// Acta Inform — 1985. — Vol. 22, —P. 187 -201. 16. Chrobak M., Goodrich M. T., Tamassia R. Convex Drawings of Graphs in Two and Three Di- mensions // Proc. 12th Annu. ACM Sympos. Comput. Geom. — 1996. — P. 319—328. 17. Chrobak M., Nakano S. Minimum-width grid drawings of Plane Graphs// Leet. Notes Comput. Sci. — 1995. —Vol. 894.—P. 104—110. 18. Chrobak M., Payne T. A linear-time algorithm for drawing planar graphs// Inform. Process. Lett — 1995, —Vol. 54.— P. 241- 246. 19. Crescenzi P., Di Battista G., Piperno A. A Note on Optimal Area Algorithms for Upward Draw- ings of Binary Trees // Comput. Geom. Theory Appl. — 1992. — Vol. 2. — P. 187—200. 20. Crescenzi P., Piperno A. Optimal-area upward drawings of AVL trees // Leet. Notes Comput. Sci. — 1995.—Vol. 894 —P. 307—317. 21. De Fraysseix H., Pach J., Pollack R. How to draw a planar graph on a grid // Combinatorica. — 1990. —Vol. 10. —P. 41—51. 22. De Fraysseix H., Rosenstiehl P. A depth-first-search characterization of planarity// Ann. Dis- crete Math. — 1982. — Vol 13 — P. 75—80. 23. Di Battista G., Eades P., Tamassia R., Tolhs I. G. Graph Drawing: Algorithms for Vizualization of Graphs. — Prentice Hall, 1999. 24. Di Battista G., Eades P.,Tamassia R., Tollis I. G. Algorithms for drawing graphs: an annotated bibliography // Comput. Geom. Theory Appl 1994. — Vol. 4. — P. 235—282. 25. Di Battista G., Liotta G., Vargiu F. Spirality of orthogonal representations and optimal drawings of series-parallel graphs and 3-planar graphs// Leet. Notes Comput. Sci.— 1993.— Vol. 709. —P. 151—162. 26. Di Battista G., Tamassia R. Algorithms for plane representations of acyclic digraphs // Theoret. Comput. Sci. — 1988, —Vol. 61. —P. 175—198. 27. Di Battista G., Tamassia R. Incremental planarity testing // Proc. 30th Annu. IEEE Sympos. Found. Comput. Sci. — 1989. — P. 436—441. 28. Di Battista G., Tamassia R., Tollis LG. Area Requirement and Symmetry Display of Planar Up- ward Drawings // Discrete Comput. Geom. — 1992. — Vol. 1. •— P. 381—401. 29. Di Battista G., Tamassia R., Tollis LG. Constrained visibility representations of graphs // Inform. Process. Lett. — 1992. — Vol. 41. — P. 1—7. 30. Di Battista G., Vismara L. Angles of planar triangular graphs // Proc 25th Annu ACM Sympos. Theory Comput. — 1993. — P. 431—437. 31. Djidjev H. N. A linear algorithm for the maximal planar subgraph problem// Leet. Notes Com- put. Sci. — 1995
1084 Часть III. Приложения 32. Dolev D., Leighton F. T., Trickey H. Planar embedding of planar graphs // Adv. Comput. Res.— 1985, —Vol. 2. —P. 147—161. 33. Drawing Graphs: Methods and Models / Kaufmann M., Wagner D. (ed) — Springer, 2001. — (Leet. Notes in Comput. Sci.; Vol. 2025). 34. Eades P., Lin T., Lin X. Minimum size h-v drawings// World Scientific Series in Comput. Sci. — 1992. — Vol. 36. — P. 386—394. 35. Eades P., Whitesides S. The Realization Problem for Euclidean Minimum Spanning Trees is NP-hard // Algorithmica. — 1996. — Vol. 16. -— P. 60—82. 36. Eades P., Wormaid N. Edge Crossings in Drawings of Bipartite Graphs // Algorithmica. — 1994,—Vol. 11. — P. 379—403. 37. Eades P., Wormaid N. Fixed Edge Length Graph Drawing is NP-hard // Discrete Appl. Math. — 1990, —Vol. 28, —P. 111—134. 38 Even S., Granot G Grid layouts of block diagrams— bounding the number of bends in each connection // Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 64—75. 39. Even S., Tarjan R. E. Computing an st-Numbering// Theoret. Comput. Sci.— 1976.— Vol. 2. — P. 339—344. 40. Formann M., Hagerup T., Haralambides J., Kaufmann M.,Leighton F.T., Simvonis A., Welzl E., Woeginger G. Drawing graphs in the plane with high resolution // SIAM J Comput. — 1993. — Vol. 22. —P. 1035—1052. 41. Garey M R., Johnson D. S. Computers and Intractability: A Guide to the theory of NP- Completeness. — New York, NY, 1979. — (есть перевод Гэри M., Джонсон Д. Вычисли- тельные машины и труднорешаемые задачи. — М.: Мир, 1982). 42. Garey М. R., Johnson D. S. Crossing number is NP-complete // SIAM J. Algebraic Discrete Methods. — 1983. — Vol. 4, N 3. — P. 312—316. 43. Garg A. On drawing angle graphs // Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 84— 95. 44. Gaig A., Goodrich M. T., Tamassia R. Area-efficient upward tree drawings // Comput. Geom. — 1993, —P. 359—368. 45 Garg A., Goodrich M. T., Tamassia R. Planar upward tree drawings with optimal area // Int. J. Comput. Geom. Appl. — 1996. — Vol. 6. — P. 333—356. 46. Garg A., Tamassia R. A new minimum cost flow algorithm with applications to graph drawing // Leet. Notes Comput. Sci. — 1997. — Vol. 1190. —P. 201—216. 47. Garg A., Tamassia R. Efficient computation of planar straight-line upward drawings // Graph Drawing '93 (Proc. ALCOM Workshop on Graph Drawing). — 1993. 48. Garg A., Tamassia R. Planar Drawings and Angular Resolution: Algorithms and Bounds // Leet. Notes Comput. Sci. — 1994. — Vol. 855. — P. 12—23. 49. Garg A., Tamassia R. On the Computational Complexity of Upward and Rectilinear Planarity Testing // Leet. Notes Comput. Sci. — 1995. — Vol. 894. — P. 286—297. 50. Garg A., Tamassia R. GIOTT03D: a system for visualizing hierarchical structures in 3D // Leet. Notes Comput. Sci. — 1997. — Vol. 1190. — P. 193—200. 51. Gregori A. Unit length embedding of binary trees on a square grid // Inform. Process. Lett. — 1989, —Vol. 31, —P. 167—172.
Приложение 2. Характеристики размещений графов 1085 52. Hopcroft J., Tarjan R.E. Efficient planarity testing// .1. ACM.— 1974.— Vol. 21, N4— P 549568 53. Hutton M. D., Lubiw A. Upward planar drawing of single-source acyclic digraphs// SIAM J. Comput. — 1996. — Vol. 25, N 2. — P. 291—311. 54. Kant G. A More compact visibility representation // Proc. 19th Internal. Workshop Graph- Thcoret. Concepts Comput. Sci. — 1993 55. Kant G. Drawing planar graphs using the canonical ordering// Algorithmica.— 1996.— Vol. 16.— P. 4—32. 56. Kramer M. R., van Leeuwen .1. The complexity of wire-routing and finding minimum area lay- outs for arbitrary VLSI circuits//Adv. Comput. Res.— 1985.-—Vol. 2. — P. 129—146. 57. La PoutreJ. A. Alpha-algorithms for incremental planarity testing// Proc. 26th Annu. ACM Sympos//Theory'Comput.— 1994. — P. 706—715. 58. Leighton F. T. New lower bound techniques for VLSI// Math. Syst. Theory'.— 1984 — Vol 17. —P. 47—70. * 59. Leiserson С. E. Area-efficient graph layouts (for VLSI) // Proc. 21st Annu. IEEE Symp. Found. Comput. Sci. — 1980 — P. 270—281. 60. Lcmpcl A., Even S_, Ccdeibaum 1. An algorithm for planarity testing of graphs// Theory of Graphs: International Symposium. —New York, 1967. — P. 215—232. 61. Lipton R. J., Tarjan R.E. Applications of a planar separator theorem// SIAM J. Comput.— 1980. — Vol. 9. — P. 615—627. 62. Liu Y_, Marchioro P., Petreschi R„ Simeone В Theoretical Results on at Most 1-Bend Em- beddability of Graphs. - Technical report, Dipartimento di Statistica, Univ, di Roma "La Sapi- enza", 1990. 63. Liu Y.. Morgana A., Simeone B. General Theoretical Results on Rectilinear Embeddability of Grupha//Acta Math. Appl. Sinica.— 1991. — Vol 7 - P. 187—192. 64. Malitz S., Papakostas A On the angular resolution of planar graphs // SIAM J. Discrete Math. — 1994. — Vol. 7. — P. 172—183. 65. Manning J. Computational complexity of geometric symmetry' detection in graphs // Leet. Notes Comput. Sci 1991. — Vol. 507.—P. 1—7. 66. Manning J., Atallah M. J. Fast detection and display of symmetry in outerplanar graphs// Dis- crete Appl. Math. — 1992. — Vol. 39. — P. 13—35. 67. Papakostas A. Upward planarity testing of outerplanar Dags // Leet. Notes Comput. Sci. — 1995 — Vol 894. — P. 298—306. 68. Papakostas A Information Visualization: Orthogonal Drawings of Graphs,— PhD thesis, De- partment of Computer Science, University of Texas at Dallas, November 1996. 69. Papakostas A., Tollis 1. G. A pairing technique for area-efficient orthogonal drawings // Leet. Notes Comput Sci -1997 Vol. 1190. — P. 354—370. 70. Papakostas A., Tollis I. G. Algorithms for area-efficient orthogonal drawings// Comput. Geom. Theory Appl. — 1998. — Vol. 9. N 1—2. — P. 83—110. 71. Papakostas A., Tollis 1. G. Improved algorithms and bunds for orthogonal drawings // Leet. Notes Comput. Sci. — 1995 — Vol. 894 - P. 40—51. 72. Papakostas A., Tollis I. G. Orthogonal drawing of high degree graphs with small area and few bends // Leet. Notes Comput. Sci. — 1997. — Vol. 1272. — P. 354—367.
1086 Часть III. Приложения 73. Reingold Е., Tilford J. Tidier drawing of trees// IEEE Trans. Softw. Eng. — 1981. — SE-7, N 2. — P. 223—228. 74 Rosenstiehl P., Tarjan R. E. Rectilinear planar layouts and bipolar orientations of planar graphs // Discrete Comput. Geom. — 1986. — Vol. 1, N 4. — P. 343—353. 75. Schaffter M. Drawing graphs on rectangular grids // Discrete Appl. Math. — 1995. — Vol. 63. — P. 75—89. 76. Schnyder W. Embedding Planar Graphs on the Grid // Proc. 1st ACM-SIAM Sympos. Discrete Algorithms. — 1990. — P. 138—148. 77. Shiloach Y. Arrangements of Planar Graphs on the Planar Lattice, — PhD thesis, Weizmann In- stitute of Science, 1976. 78. Shin С.-S., Kim S K., Chwa K.-Y. Area-Efficient Algorithms for Upward Straight-Line Tree Drawings // Leet. Notes Comput. Sci. — 1996. — Vol. 1090. — P. 106—116. 79 Storer.1. A. On minimal node-cost planar embeddings// Networks.— 1984.— Vol 14.— P. 181—212. 80 Supowit K. J., Reingold E. M. The complexity of drawing trees nicely // Acta Inform. — 1983, —Vol. 18, —P. 377—392. 81. Tamassia R. On embedding a graph in the grid with the minimum number of bends// SIAM J. Comput. — 1987. — Vol. 16, N 3. — P. 421—444. 82. Tamassia R., Tollis I. G. A unified approach to visibility representations of planar graphs // Dis- crete Comput. Geom. — 1986. — Vol. 1,N4. — P. 321—341. 83. Tamassia R., Tollis I. G. Planar grid embedding in linear time// IEEE Trans. Circuits Syst. — 1989. — CAS-36, N9. — P. 1230—1234. 84. Tamassia R., Tollis I. G. Tessellation representations of planar graphs // Proc. 27th Allerton Conf. Commun. Control Comput. — 1989. — P. 48—57. 85. Tamassia R.,Tollis 1. G., Vitter J.S. Lower bounds for planar orthogonal drawings of graphs// Inform. Process. Lett. — 1991. — Vol. 39. — P. 35—40. 86. Trevisan L. A note on minimum-area upward drawing of complete and Fibonacci trees // Inform. Process. Lett. — 1996. — Vol 57, N 5. — P. 231—236. 87. Tutte W. T. Convex representations of graphs// Proc. London Math. Soc. — 1960. — Vol. 10, N 3. — P. 304—320. 88. Tutte W. T. How to draw a graph// Proc. London Math. Soc.— 1963.— Vol. 13, N 3.— P. 743—768 89. Valiant L. Universality considerations in VLSI circuits// IEEE Trans. Comput.— 1981.— C-30, N 2. — P. 135—140. 90. Van Leeuwen J. Graph algorithms // Handbook of theoretical computer sciences. — Elsevier Sciencs Publishers В. V., 1990. — Vol. A. — P. 526—631.
Предметный указатель D //морфизм орграфов 1030 F F-линия 750 F-луч 262 F-область 263 f-подграф 790 f-порядок 790 F-путь 96 F-ранг 751 К К векторов 1046 К кратчайших путей 1042 К наилучших остова 1038 К подмножеств 1046 //замыкание 1036 АГ-определяемость 1064 L li-множество 970 Н-сечение 970 Р Р-схема. О реализуемая О-схемой 888 R R-редукция 307 S SSA-форма 886 А Автомат: О конечный 544 О МП 550 О с магазинной памятью 550 А-граф 749 Алгоритм: О Винтера 160 О вычисления атрибутов: ° детерминированный 595 ° динамический 594 ° недетерминированный 595 ° статический 595 О Габова 172 О Горальчиковой-Коубека 203 О Дейкстры 45 О динамическдго программирования 697 О Диница 52 О Жомард-Мину 206 О Карзанова 53 О Касьянова 248 О Краскала 146 О полиномиальный 1021 О Прима 147 О простой итеративный 799 О с рабочим списком 799 О с укладкой 800 О Симона 205 О Соллина 149 О Тарьяна 245 О Тарьяна — Черитона 149 О факторизованный 801 О Фараджева 247 О Флёри 30 О Форда 44 О Форда — Фалкерсона 52 О Чена 164 О Эдмондса 154 О Эрли 565 Алфавит 535
1088 Предметный указатель Альт 260 О аранжируемый 271 О внешний 747 О внутренний 747 О неаранжируемый 271 Анализ: О восходящий 550 0 горизонтальный 550 О конечных автоматов 940 О нисходящий 550 О синтаксический 534 Анализатор: О LL556 О лексический 546 Аннотация 899 Антицепь I88, 946 Апекс 717 А-представление 748 Аранжировка 271 Аргумент 736 О необязательный 742 О обязательный 742 Атрибут 531 О наследованный 590 0 наследуемый 590 О полезный 595 0 синтезированный 590 0 синтезируемый 590 Атрибутная грамматика 590 О I 603 О L-атрибутная 611 О S603 О в нормальной форме 591 О нормализованная 591 0 чисто наследуемой 603 О чисто синтезируемой 603 Ахроматическое число 1031 0 дополнения 1031 Б Базис: 0 графа пересечений 1036 О семейства 1046 О 3-множеств 1046 Библиотека: 0 AGD430 О ffGraph 431 0 GET 431 О GLT431 0 Graph Drawing Server 431 О LEDA 430 Бикомпонента 43, 243 Бинарная диаграмма решений 915 О упорядоченная 916 Блок 24, 947 Братья 62 В Вектор 1024 О каркаса 33 Величина (мощность) потока 50 Вершина 21 О F-достижимая 96 О ассоциативно-коммутативная 721 О входная 188, 259 0 выходная 188, 259 О головная цикла 868 О граничная 259 0 достижимая 43 О зависящая по управлению 859 О инцидентная 27 0 коммутативная 720 0 конечная 259 О концевая (граничная) 22 О легкая 230 О начальная 259 О переменная 829 О покрывающая дугой 285 0 простая 865 О составная 865 О специальная 767 О стартовая 259 О тяжелая 230 О фиктивная 384 0 финишная 259 О функциональная 829 О центральная 32 0 цикловая 865 Вершинная база 189 Вершинное: О дерево вложенности 401 О покрытие 1031 ° планарного графа 1031 Веса 95 Весовой критерий: О логарифмический 1019 0 равномерный 1019 Ветвление со многими вариантами 1038 0 в сильно связном графе 1038 Взвешенный диаметр 1036 Вложение: О гомеоморфное 27, 1005 О изоморфное 27, 1005 О ребер в решетку 1044
Предметный указатель 1089 Внешность 339 Вполне предупорядочение 849 Временная сложность 1020 ВУ-язык 1023 Вход 188, 259 О информационный 736 Вхождение: О атрибута 590 О использующее 586 О определяющее 586 О подтерма 819 Вывод 537 О левый 540 О правый 540 Выживаемость сети 1041 Выполнение: О формулы 1059 О 3-формулы 1059 Выполнимость 1058 О булевых выражений 1058 ° над полным набором связок 1058 О 3-выполнимость 1058 ° монотонная 1058 ° ограниченная при одном истинном литерале 1058 ° при различных литералах 1058 Выражение О избыточное 797 О регулярное 573 Высота 62, 803 О вершины 227 О дерева 227 О конечная 803 О разбиения 384 О строго конечная 803 О элемента 946 Выход 188 О информационный 736 Вычисление: О непрерывное 697 О ограниченное 1055 О семейства 1053 Вычислитель: О восходящий 595 О динамического размера 603 О нисходящий 595 О оптимальный по времени 595 О сверху вниз 595 О снизу вверх 595 О статического размера 603 О управляемый данными 595 О управляемый запросами 595 Г Гамак 260 О неразложимый 748 О простой 748 О разложимый 748 О составной 748 Гамильтонов: О путь 1036 ° двудольного графа 1036 ° орграфа 1036 п планарного графа 1036 О цикл 1036 ° двудольного графа 1036 ° квадрата 1036 ° ориентированный 1037 ° планарного графа 1036 п реберного графа 1036 Гамильтоново пополнение 1031 Генерация: 0 по времени 139 0 кода: ° для параллельных присваиваний 1053 ° на одноадресной регистровой машине 1053 ° с неограниченным числом регистров 1053 0 по номеру 139 0 прямая 139 0 ограниченная 1055 Гиперкривая 406 Глубина: 0 аранжируемого уграфа 272 0 вершины 227 0 дерева 227 0 нумерации 272 "Го" на доске n х п 1059 Гомоморфизм графов 1031 Грамматика 536 0 LR 566 0 LR(k) 566 0 автоматная 537 0 ациклическая 592 0 без е-правил 542 0 без левой рекурсии 543 0 без цепных правил 542 0 без циклов 542 0 графовая 411 0 контекстно-зависимая 538 0 контекстно-свободная 537 0 корректная 592 0 КС 537 0 КС редуцированная 590 0 неукорачивающаяся 538 Продолжение рубрики см. на с. 1090
1090 Предметный указатель Грамматика (прод.): О простого предшествования 559 О с фразовой структурой 538 О составляющих 536, 538 О типа 0 538 О типа 1 538 О типа 2 537 О типа 3 537 О эквивалентная 540 0 языка 528 Грамматические элементы языка 531 Граница 403 0 верхняя 945 0 грани 28, 352 0 множества термов 823 0 нижняя 944 Грань 28, 352 0 верхняя 945 0 внешняя 29, 353 0 внутренняя 353 0 нижняя 945 Граф 21 0 h-реберно связный 25 О k-вершинно связный 23 О к-реберно раскрашиваемый 38 0 к-регулярный 25 О st 366 О ациклический 187 О бесконечный 22 О бесконтурный 187 О блоков 24 О блоков и точек сочленения 24 0 внешнепланарный 1006 0 вызовов 739 0 выпуклый прямоугольный 353 0 гамильтоновый 30 0 Герца 244 0 гомеоморфный 352 0 данных 72, 998 0 двудольный 23 0 двудольный полный 23 0 зависимости по данным 855 0 зависимости по управлению 872 0 заданий иерархический 865 0 зацепленности 739 0 интервальный 36, 948 0 информационный 737, 884, 886, 893 0 КА 742 0 клик 35 0 конденсации 244 0 конечный 22 0 косвенной адресации 742 0 Куратовского 29 0 локальной зависимости 591 0 маркированный 987 0 нагруженный 95 0 несовместимостей регистров 678 0 несовместимости 885 0 одновходовый 260 0 основной 399 0 переплетения 354 0 пересечений отрезков решетки 1044 0 планарный 28, 352 0 плоский 28, 352 0 полного упорядочения 947 0 полный 22 0 помеченный 95 0 последовательно-параллельный 190, 363 О поуровневый ациклический 384 О программных зависимостей 860 О производный 265 О простой (обыкновенный) 22 О процедур 739 О пустой 22 О разметок 976 О расширенный 768 О реализации: ° информационный 409 ° информационно-логический 409 0 реберный 26 0 регулярный 25 0 с косвенной адресацией 897 0 синхронизационный 987 0 составной зависимости 591 0 степенно-хордальный 35 0 строго хордальный 36 0 триангулированный 34 0 управляющий 258, 893 0 хордальный 34, 948 0 частичный 26 Группировка с помощью транспозиций 1049 д Двусвязное пополнение 1041 Декодирование линейных кодов 1069 Делимость показательного выражения 1062 О ограниченная 1062 Дерево 31 О PQ356 О абстрактное синтаксическое 597 О атрибутированное 591 О атрибутное 591 О бинарное 66 О бицентральное 33 0 вложенности 399
Предметный указатель 1091 О входящее 6I О вывода 539 О выражения 597 О выровненное 62 О вырожденное 31 О выходящее 61 О глубинное остовное 99 О декомпозиционное 363 О доминаторное 262 О заполненное 591 О иерархическое 402 О иерархическое упорядоченное 402 О концевое доминаторное 285 О корневое 61 О левостороннее бинарное 67 О левых выводов 554 О ориентированное 61 О остовное 33 О плоское 62 О покрывающее 713, 979 О покрывающее полное 980 О постдоминаторное 262 О правостороннее бинарное 67 О пустое 31 О разбора 364, 539 0 растущее 62 О редукций 557 0 решений 1069 0 свободное 61 О сжатое 230 О стягивающее 33 О тривиальное 31 О упорядоченное 62 0 Хусими 24 О частичное 717 0 Штейнера 1039 ° геометрическое 1039 ° минимальное 40 ° на двудольном графе 1039 ° на планарном графе 1039 Диаграмма: 0 переходов 545 0 Хассе 945 Директива 899 Длина 0 интервального представления 266 0 цепи 40 Доминатор: 0 внешний 767 0 внешний продвинутый 767 Доминирующее множество 1031 0 графа: ° степени 3 1031 ° планарного 1031 Дополнение до матрицы со свойством связности 1049 0 циклической 1049 Допускаемость Л О-автоматом 1056 0 детерминированным 1056 Допустимость назначения регистров 1053 0 ограниченная 1055 Достаточность числа регистров 1053 0 ограниченная 1055 Достижимость в консервативных сетях Петри 1069 Достоверные соотношения частот выполнения 741 Древесность 61 Дуга: 0 F-обратная 95 0 вперед 272 0 древесная 99 0 назад 272 0 обратная 99 0 поперечная 100 0 прямая 99 Дэг 187 О выражения 600 0 корневой 188 0 луча 679 0 связный 187 Е Емкостная сложность 1020 Е-переход 982 Ж Живость сетей Петри со свободой выбора 1069 3 Задача. 0 NP-полная 1022 0 абстрактной интерпретации 792 0 автономная 228 0 битвекторная 809 0 внутрипроцедурная 809 0 глобального потокового анализа 792 0 глубины 229 0 глубины пса 229 0 квалифицированных путей 793 0 класса NP 1021 Продолжение рубрики см. на с. 1092
1092 Предметный указатель Задача (пред.): О коммивояжера 1042 п геометрическая 1042 ° для двух расстояний 1043 ° с ограниченными расстояниями 1043 0 межпроцедурная 809 0 нахождения свойств состояний 792 0 о минимальной связке 40 0 о подъемном кране 1043 0 обратная 792 0 отыскания кратчайшего пути 43 0 прямая 792 0 разложимая 809 0 разметки 350 О с соединением 228 О с соединением и разрезанием 228 О с соединением корней 228 О со статическими деревьями 228 О труднорешаемая 1021 Зазор ребра 384 Замкнутая окрестность 26 Замыкание 210 О быстрое 807 О вершины 210 О зависимости 226 О конгруэнтное 211 О обратое 210 О относительно вершины 210 О псевдораскраски 895 О псевдотранзитивное 808 О симметричное конгруэнтное 223 О транзитивное 947 Запись 1024 0 активации 653 Значение: О термальное 409 Зона 260 И Идеал .957 Идентификация 586 Иерархический граф 399 О планарный 404 О простой 401 0 связный 400 Иерархия: О вложенных альтов 748 О вложенных зон 270 О фрагментов 399 О Хомского 538 Изображение: О hv 360 О восходящее 337 О иерархического графа 403 О неструктурное 404 О нисходящее 337 О ортогональная 336 О плоское 337, 404 О полилинейное 336 О полное 404 О прямолинейное 336 0 сетчатое 337 О структурное 403 О частичное 404 О шинно-ортогональное 364 Изоморфизм подграфу 1032 Имена: О временные 644 0 промежуточные 644 О рабочие 644 Инварианты 407 Индекс: О вершинно-хроматический 38 О реберно-хроматический 38 Индукция: О атрибутная 586 О семантическая 586 Интервал 260 Интервальное представление уграфа 266 Интерпретация 736, 874 0 нерезультативная 877 О результативная 877 0 свободная 880 О эрбранова 880 Информационная: 0 несовместимость 737 О связность 737 Инцидентор 21 Искаженность 371 Использование физических аналогий 339 История: О логико-термальная 409 О операционная 409 О операционно-логическая 409 Итерация языка 536 К КА-граф 897 Каркас 33 О оптимальный 144 О уграфа 269 КА-схема 893 О правильная 896
Предметный указатель 1093 Квадратичная задача о назначении 1044 Квадратичные сравнения 1062 Квадратные диофантовы уравнения 1062 Квазипорядок 947 Квантификация переменной 923 Китайский почтальон для смешанных графов 1043 Класс: О корневой 830 О эквивалентности гомогенный 829 Кластер 339, 722 Клика 34, 1032 Ключ 876 Код: О Гапта 85 О главный уровневый 82 О Закса 84 О Ли 84, 85 О линейный 78 О Прюфера 74 О ротационный 82 О трехадресный 644 О уровневый 81 ° канонический 81 Кодирование: О оптимальное 78 Композиция 820 Компонента: О двусвязности 24 О линейная 260 О сильной связности 43, 243 Конкатенация 535, 536 Конкретизация 901 О полная 901 Контрабаза 189 Контур 43 О простой 43 Корень 61 О бикомпоненты 244 О дэга 188 О основной 81 Коэффициент производительности 351 Кратность дуги 974 Кратные дуги 41 Кратчайшая обшая подпоследовательность 1049 О в двоичном алфавите 1050 Цепь 40 Кратчайшее общее надслово 1050 О в двоичном алфавите 1050 Кратчайший путь: О в графе с ограничением по весу 1043 О в орграфе с ограничением по весу 1043 Л Лексема 529 О семантическая 586 Лексическая свертка 534 Лемма Цорна 945 Лес 31 О глубинный остовный 99 О доминаторный 285 О обхода 96 О остовный 99 О с ограниченными по весу компонентами 1039 О с ограниченными по числу вершин компонентами 1040 Линейное упорядочение с минимальным разрезом 1036 Лист 62 Луч 260 О эквивалентный 662 м Максимальная: О симметричность 338 О 2-выполнимость 1058 Максимальное: О взвешенное паросочетание 1059 О паросочетание 1032 ° двудольного графа 1032 ° планарного графа 1032 ° подграфов 1031 Маркировка: О сети 974 Маршрут 22 О информационной связи 884 О пары 887 Массив программный 643 Масштаб 879 Матрица: О достижимости 43, 199 О инцидентности 27 О пересечений 1047 ° 3-множеств 1046 О переходов 545 О смежности 26 Машина: О поинтерная 243 О равнодоступная адресная 1017 О трансформационная 901 Мера 778 О модифицированная цикломатическая 783 О объемная 779 Продолжение рубрики см. на с. 1094
1094 Предметный указатель Мера (прод.)-. О Пивоварского 783 О тестирующая 784 О топологическая 779 О функциональная 782 О цикломатическая 779 Место безопасное 978 Метод: О Локальной замены 1023 0 нелокальной схематизации 892 0 построения компонент 1023 0 потоковый 340 0 Сигаяма-подобный 340 0 сужения 1022 Метрика: 0 гибридная 779 0 комплексная 779 0 потока данных 779 Метрическая размерность 1036 Микродерево 767 0 нетривиальное 767 0 тривиальное 767 Минимальная дизъюнктивная нормальная форма 1058 Минимальное 0 множество тестов 1047 ° для 3-множеств 1047 0 покрытие 1047 ° 3-множеств 1047 0 разделяющее регулярное выражение 1056 ° ограниченное 1057 Минимальный: 0 Л-связный подграф 1032 0 разделяющий конечный автомат 1056 0 эквивалентный орграф 1033 Минимизация: 0 веса невыполненных в срок заданий 1066 0 взвешенного момента окончания 1067 0 взвешенного момента окончания для двух процессоров 1067 0 длины ребра 338 0 коэффициентов сторон 338 0 области пересечений 338 0 общей длины ребер 338 0 пересечений 337 0 разрешений 338 0 сгибов 338 0 сгибов на ребре 338 0 числа блоков 1050 ° ограниченная 1050 0 числа заданий, невыполненных в срок 1067 ° ограниченная 1067 0 числа фиктивных работ 1044 0 штрафа за невыполненные в срок задания 1067 Минимум суммы квадратов 1047 Многовходовая зона 260 Множество: 0 вершин, разрезающих контуры 1032 ° орграфа степени 2 1031 ° планарного графа 1032 0 (непосредственно) вложено 299 0 дуг, различающее пути 1036 0 дуг, разрезающих контуры 1032 ° орграфа степени 3 1032 0 дуг, частично разрезающих циклы 1032 0 зацепленное 299 0 квазиупорядоченное 947 0 линейно упорядоченное 943 0 мультуравнений: п компактное 823 0 накрывающее 1059 0 независимое 197, 1033 ° двудольного графа 1033 ° планарного графа 1033 0 несравнимое 197 0 ограниченное 806 0 однородно ограниченное 806 0 оценочное 778 0 представителей 1047 D 2-множеств 1047 0 регулярное 538, 573 0 соответствующее мультиуравнению 822 0 уравнений: п в разрешенной форме 820 ° эквивалентные 820 0 частично упорядоченное 943 Модель: 0 иерархическая графовая 407 0 решеточная 966 0 с перемещениями 349 0 с фиксированными позициями 349 0 с фиксированными позициями и масштабируемыми метками 349 0 семантическая 408 0 формальная 408 Монохроматический треугольник 1033 Мост 25 Мультиграф 22 Мультикоманда 643 Мультитерм 828 Мультиуравнение 822 н Набор 1025 Наглядность 349 Надежность сети 1041 Недвусмысленность 349
Предметный указатель 1095 Неориентированный поток, ограниченный снизу 1044 Непересекающиеся: О пути 1044 ° ограниченные 1044 О соединяющие пути 1045 Неравенства Визинга 38 Несвободность моноидной стандартной схемы: О ациклической с двумя переменными 1053 О без циклов 1053 Нетерминал 536 Неуниверсальность: О регулярного выражения 1056 0 регулярной грамматики 1056 Неэквивалентность: О ациклических схем Янова 1053 0 композиций сложения и деления по модулю 1053 О композиций сложения и максимума 1054 О композиций условных функций 1054 О конечных автоматов 1056 О линейных программ: ° с массивами 1054 ° с условными присваиваниями 1054 0 моноидных рекурсивных схем 1054 0 ограниченная конечных автоматов 1056 ° с общим одноэлементным входным алфа- витом 1056 0 ограниченная линейных программ: ° с массивами 1055 ° с условными присваиваниями 1055 0 программ: ° без вложенных циклов 1054 ° с конечной памятью 1054 0 простых функций 1054 0 регулярных: ° выражений 1056 ° грамматик 1056 0 схем Янова 1055 ° ограниченная 1055 0 целочисленных выражений 1062 Нижняя пропускная способность 51 Нормальная форма: 0 Грейбаха 543 0 терма 841 0 Хомского 543 Носитель: 0 графа 189 0 частичного порядка 948 Нумерация 95, 1025 0 К 750 0 L751 0 М 96 0 N96 0 st 355 0 базисная 97 0 графа по Грунди 1037 0 обратная 96 0 правильная 262 0 прямая 96 0 разумная 272, 747 О Область 311 0 действия 586 0 интерпретации 876 0 сильно связная 260 Облицовка квадрата 1059 Обобщенная: 0 география 1060 ° планарная 1060 0 игра в кубики 1060 Обобщенные "Кейли" 1060 0 на двудольном графе 1060 Обобщенный "гекс" 1060 0 ориентированный 1060 ° реберный 1061 Обход 96, 1025 0 в глубину 99 0 в ширину 98 Общая подпоследовательность наибольшей длины 1050 Общий вес 1047 Объединение 949 Ограниченная генерация кода для параллельных присваиваний 1055 Ограниченное присвоение истинности с разбиением множества переменных 1061 Ожидаемая стоимость поиска 1051 0 в фиксированном числе сегментов 1051 Окрестность вершины 34 Операнд 736 0 взаимно достижимый 888 0 информационно достижимый 884 Оператор 0 прерывания 1028 0 присваивания 1027 0 процедуры 1029 0 расширения 809 0 составной 1027 0 условный 1027 0 функции 1029 0 цикла 1028 Операция: 0 APPLY 923 0 RESTRICT 927 Продолжение рубрики см. на с. 1096
1096 Предметный указатель Операция (прод.): О выделения: ° корня 64 ° правого брата 64 О дистрибутивная 957 О именования 892 О консенсуса 923 О непрерывная 957 О отделения поддерева 64 О перестановки поддеревьев 64 О подклеивания 64 О подразбиения 352 О разыменования 892 О сглаживания 923 Оптимальное линейное упорядочение 1037 О двудольного графа 1037 О орграфа 1037 Оптимизация: О покадровая 700 О программ 641 О шелевая 700 Организация памяти в виде корневого дерева 1051 Орграф 41 О (п,т)-орграф 41 О восходящий планарный 353 О односторонне связный 43 О сильно связный 41 О складной 190 О слабо связный 43 О транзитивный 947 О циклически сводимый 305 Ордерево 61 Ориентированная петля 41 Ориентированный диаметр 1037 Ормаршрут 41 Основа 43. 590 Основа гиперкривой 407 Остов 33 О геометрический с ограниченной пропускной способностью 1039 О изоморфный: ° 3-звезде 1039 ° дереву 1039 ° полному бинарному дереву 1039 ° пути 1039 О ограниченного диаметра 1040 ° графа с двумя весами ребер 1040 0 ограниченной степени 1040 0 оптимальный коммуникационный 1040 О планарного графа 1040 0 регулярного графа 1040 О с кратчайшим полным путем 1040 О с максимальным числом висячих вершин 1040 О с ограниченной пропускной способностью 1040 ° для сетей 1041 О-схсма 886 Открытая полусфера 1065 Отношение: О бинарное 198 О вполне фундированное 848 О вход-выход 592 О выход-вход 592 О доминирования 262 О достоверное частотное 298 О инцидентности 973 О локальной зависимости 591 0 наследуемых зависимостей 592 О нетеровое 848 О обязательного: ° предшест вования 262 ° следования 262 О постдоминирования 262 О причинной зависимости 969 О редукции 840 О синтезируемых зависимостей 591 О эквивалентности допустимое 829 О эквивалентности нетривиальное 881 Отсутствие: О наложений 349 О тавтологии 1059 ° ограниченное 1059 Ошибка лексическая 549 п Пара критическая 842 Паросочетание 198 О максимальное 198 О наибольшее 198 О с ограничениями по весу 1048 О со многими вариантами 1037 Перевод 571 О локальный 891 О синтаксически управляемый 571 Переименование временных переменных 663 Переменная: О активная 659 О живая 659 О занятая 659 О используемая 659 О константная 796 О несовместимая 885 О определяемая 659 О совместимая 885
Предметный указатель 1097 Пересечение 949 О для конечных автоматов 1057 Перестановка: О дерева 722 О операторов 663 Переход: О живой 979 О мертвый 979 О потенциально живой 978 О потенциально мертвый 979 О устойчивый 979 Периодическое решение рекуррентного уравнения 1063 Перманент 1062 Планаризация 339 Планарная часть графа 1033 Подграф 27 0 двудольный 1031 О двудольный графа степени 3 1031 О двудольный связный 1031 О запрошенный 268 О иерархический 400 О кубический 1032 О логический 1069 О наиболее обший 1033 О односторонне связный 1033 О планарный 1033 О порожденный: ° вершинами 27 ° ребрами 27 ° связный с наследуемым свойством 1034 ° с наследуемым свойством 1033 О реберный 1035 О реберный графа: ° степени 3 1035 ° степени4 1035 О сбалансированный полный двудольный 1035 0 связный ограниченной степени 1035 О транзитивный 1035 Подматрица со свойством: О связности 1051 О циклической связности 1051 Подрешетка 952 О выпуклая 953 Подстановка регулярного выражения 1051 Подтерм 819 Подуграф 786 Подфрагмент 259 О прямой 399 О собственный 259 Подцепочка 536 Поиск: О в глубину 99 О в ширину 98 Покомпонентные неравенства 1065 О между двоичными векторами 1065 Покрытие 0 кликами 1033 0 полными двудольными подграфами 1033 О Рейнольдса: ° для КС-грамматик 1057 ° для регулярных грамматик 1057 Полупуть 43 Полурешетка 956 О замкнутая 803 О нижняя 956 О свойств 794 Пометка 95, 794 О начальная 794 Понижение силы операций 703 Понятия 530 Пополнение: 0 до графа: ° интервалов 1033 ° путей 1033 0 реберно связное 1042 0 сильно связное 1042 0 СПТ 845 Порождение: О полное 126 0 равновероятное 126 Порядок 22 0 антилексикографический 949 О вычисления атрибутов 594 О доминирующий 949 0 интервальный 36 О инфиксный 109, 115 О лексикографический 949 О постфиксный 109, 115 О префиксный 109, 115 0 совершенный элиминирующий 35 0 строго элиминирующий 36 Последовательное исключение степеней 1037 П оследовательность: 0 полная 305 0 сведения 269 О сверху вниз 339 » О слева направо 339 Поток 50 О в сети с ограничениями 1045 0 данных 737 О минимальной реберной стоимости 1045 О минимальный 51 О наибольший 50 О оптимальный 51 Продолжение рубрики см. на с. 1098
1098 Предметный указатель Поток (пред.): О целочисленный в сети ° с гомологичными дугами 1045 ° с расслоениями 1045 ° с умножителями 1046 Потомок 227 Правило 536 0 видимости 586 0 левое расширенное 363 0 переписывания термов 840 0 правое расширенное 363 0 семантическое 590 Правильная часть 738 Прагматика 527 Предложение 537 Предок 227 0 ближайший общий 227 Представимость: 0 конечной функции 1069 0 целочисленным выражением 1063 Представление: 0 BDD915 0 OBDD 916 0 в виде: ° корневого дерева 1037 ° троек 644 0 вершинное 401 0 восходящее 353 0 выпуклое 374 0 гамачное 749 0 дерева 67 0 древесное 959 0 конечных областей 930 0 множеств 932 0 мозаичное 366 0 обзорное 364 0 обзорное st-графа 367 0 отношений 932 0 со свойством связности 1052 0 четверками 644 Предупорядочение 848 0 Крушкаля 850 0 упрощающее 849 Предшественник: 0 внутренний непосредственный 768 0 непосредственный обязательный 262 Преемник непосредственный обязательный 262 Преобразование: 0 анализирующее 901 0 компактификации 824 0 конкретизирующее 901 0 корректное 900 0 обобщающее 900 О повторное 701 О расщепления 197 О специализирующее 901 О сужающее 900 О Т1 190, 272 О Т2 190, 272 О ТЗ 190, 279 О типа 998 О Хака 985 О эквивалентное 407, 900 О элементарное 33 Преобразователь 544, 737 О пометок 794 О свойств 794 Префикс 536 О собственный 536 Принадлежность: О детерминированному КЗ-языку 1057 О КЗ-языку 1057 Приписывание регистров 649 Присваивание: О необязательное 876 О обязательное 876 Присвоение истинности с разбиением множества переменных 1061 Проблема: О максимизации: ° количества 350 ° размера 350 О разрешимости 350 О точного мониторинга 963 Программа: О N-оптимальная 722 О аннотированная 900 О базисная 899 О вычисляющая 899 О квазибазисная 900 О обобщающая 899 О хорошо определенная 900 Программирование: О 0-1 целочисленное 1064 О квадратичное 1064 О линейное: ° с параметрической целевой функцией 1064 ° фиксированное с параметрической целевой функцией 1066 О целочисленное 1066 Продукция 536 О графовая 411 Произведение: О адамарово 244 О размеров 1048
Предметный указатель 1099 Пропускная способность 50 0 верхняя 197 0 нижняя 197 Просмотр 532 Прямоугольное сжатие картинки 1052 Псевдограф 22 Псевдораскраска 894 0 корректная 895 Путевое покрытие вершин 197 0 минимальное 197 Путь 41 0 Sdom 757 0 XDOM 767 0 внешний доминаторный 767 0 допустимый 878 0 несокращаемый 311 0 порожденный двудольного графа 1034 0 порожденный путь 1034 0 простой 41 0 с запрещенными парами 1038 0 семидоминаторный 757 Р Разбиение 1048 0 ациклическое на ограниченные части 1041 0 графа 1042 ° на ограниченные части 1042 0 на гамильтоновы подграфы 1034 0 на два паросочетания 1034 0 на изоморфные подграфы 1034 0 на классы эквивалентности 213 0 на клики 1034 0 на леса 1034 0 на матрицы со свойством связности 1052 0 на подграфы, изоморфные фиксированному графу 1034 0 на пути длины 2 1034 О на равные подмножества 1048 0 на совершенные паросочетания 1034 ° планарных графов 1035 0 на треугольники 1035 0 со свойством связности 1052 D ограниченное 1050 0 3-разбиение 1046 Разбор 534 Размер 22 0 вершины 230 Размерность: 0 Нешетрил—Редл 1038 0 частичного порядка 946 0 элемента 946 Разметка 1025 0 /-тупиковая 979 0 вершин 95 0 достижимая 975 О корректная 795 0 места 974 0 насыщающая 795 0 начальная 974 0 полная 794 0 сети 974 0 стационарная 795 0 тупиковая 976, 979 0 хорошая 795 Размещение файла с дублированием 1052 0 однородное 1050 Разрез: 0 максимальный однородной сети 1041 0 минимальный с ограничениями 1041 РАМ 1017 0 недетерминированная 1022 Ранг: 0 операнда 896 0 переменной 896 Ранжирование по максимуму правдоподобия 1069 Раскраска 876, 893 0 вершин 38 0 допустимая 885 0 ребер 38 Раскрашиваемость графа 1035 0 в три цвета 1035 0 планарного 1035 РАСП 1021 Расписание: 0 двухпроцессорное 1066 0 для двух процессоров 1068 0 для одного процессора 1068 0 многопроцессорное 1067 0 с индивидуальными директивными сроками 1068 0 с ограниченными ресурсами 1068 0 с ограниченными ресурсами ограниченное 1067 0 с прерываниями 1068 0 с условиями предшествования 1068 О с условиями предшествования ограниченное 1068 0 учебное 1068 Распознаватель 543, 737 0 детерминированный 544 0 недетерминированный 544 0 с выходом 544 Расположение радиальное 358
1100 Предметный указатель Распределение: О глобальное 674 О каноническое 885 О статическое 654 О стековое 655 О регистров 649 Расстояние 32 Расщепление 1048 0 3-множеств 1048 0 вершины 279 0 многовходовых зон 281 0 альтов 280 Реализация графа данных 1003 Ребро 21 0 инцидентное 27 Регион 860 Редактирование слова 1052 Редукция: 0 мультиуравнения 823 0 не полностью определенного конечного автомата 1057 0 полностью определенного недетерминированного конечного автомата 1057 0 термов 821 0 фиксированная не полностью определенного конечного автомата 1058 Результат 736 0 необязательный 741 0 обязательный 741 0 применения подстановки 820 Рекурсивный спуск 557 Решение системы линейных уравнений 1064 Решетка 949 0 динамической структуры 966 0 дистрибутивная 954 0 модулярная 955 0 полная 804 0 полумодулярная 955 0 с дополнениями 955 0 симплициальная 960 0 Юнга 951 Род графа 371 Ротация: 0 левая 82 0 правая 82 Р-схема 886 Рюкзак 1066 0 непрерывный 1064 0 непрерывный ограниченный 1065 0 ограниченный целочисленный 1065 0 ограниченный частично упорядоченный 1065 0 частично упорядоченный 1066 С Самый длинный путь 1043 0 во взвешенном графе 1043 Самый длинный цикл 1043 0 во взвешенном графе 1043 Свойство: 0 исполнений 791 0 состояний 792 0 Черча — Россера 411, 841 Связывание 531 Связь. 0 информационная 737, 892 895 0 управляющая 737, 892 Сельский почтальон 1043 0 в однородной сети 1044 Семантика 527 Семидоминатор 757 (а,Ь)-сепаратор 35 Сеть 50, 973 0 СРМ 196 0 PERT 196 0 автоматная 987 0 безопасная 978 0 живая 979 0 иерархическая 996 ° помеченная 998 0 ингибиторная 989 0 конечная 974 0 консервативная 978 0 кратчайшая связывающая 144 0 ординарная 974 0 Петри 974 ° помеченная 982 0 потоковая 197 0 раскрашенная 990 0 с приоритетами 989 0 свободная 988 0 со свободным выбором 988 0 устойчива 979 Сечение дерева 404 Сжатие разреженной матрицы 1052 0 ограниченное 1050 Сжатое разбиение 384 Символ: 0 внешний 819 0 корневой 819 0 начальный 536 Синтаксис 527 Синхрограф 987 Система: 0 daVinci 416 0 GraphEd 421
Предметный указатель 1101 О Graphlet 421 О GraVis 423 О HIGRES 436 О SmartDraw 426 О VCG 418 О VEGRAS 428 О VGJ 425 О в триангулярной форме 824 О информационных связей 737 О мультиуравнений 824 О несравнимостей 1063 О переписывания: ° графов 411 D термов 840 О полная 883 0 преобразований: ° полная 410 Сканер 546 Скопления 1070 0 ограниченные 1069 Слияние двух вершин 272 Слово 535 0 выбора 876 0 применимости 876 Сложность цикломатическая 780 Слой 232 Смежные ребра 26 Смешанная стратегия 642 Совместная делимость линейных многочленов 1063 Со-множество 971 Соответствие ограниченное 1050 Соотношение "между" 1070 Соседи 62 Со-сечение 971 Составление кроссворда 1061 Состояние- 0 начальное 877 0 памяти 877 Список 1025 0 двусторонний 1025 0 односторонний 1025 СПП 351 СПТ 840 0 каноническая 842 0 конвергентная 842 0 конечно завершимая 842 0 конфлюэнтная 841 0 локально-конфлюэнтная 842 0 несводимая 851 0 нетерова 842 0 полная 842 Сравнительная делимость 1063 0 ограниченная 1062 Сравнительное содержание 1048 0 однородное 1048 Стандартное представление уграфа 267 Стандартное преобразование 282 Степенная последовательность 25 Степень: 0 вершины 25 0 графа 25 Стоимость команды 652 Строка 535, 1024 Структурная неэквивалентность 1057 0 регулярных грамматик 1057 Стягиваемость графа 1035 Суграф 26 Сужение 899 Сумма размеров 1066 Суффикс 536 0 собственный 536 Схема: 0 информационно эквивалентная 884 0 крупноблочная 876 0 Мартынюка 738, 880 0 моделирующая 879 0 над общей памятью 741, 886 0 над распределенной памятью 741, 886 0 неинтерпретированная 880 0 правильная 738 0 программы 736 0 процесса трансляции 532 0 свободная 878 0 свойств состояний 794 0 семантическая 874 0 с косвенной адресацией 893 0 с разметкой 794 0 стандартная 881 0 СУ 572 0 трансляции деревьев 705 0 трансляционная 611 0 формальные 875 0 функционально эквивалентные 874, 877 0 хорошо определенная 794 0 Янова 882 Схематизация программ 875 Сцепление 535 т Таблица: 0 объектов 643 0 сигнатур 213 Теорема: 0 Харари — Принса 90 Продолжение рубрики см нас. 1102
1102 Предметный указатель Теорема (прог).): О Ахо — Джонсона — Ульмана 695 О Брукса 39 О Бруно — Сети 695 О Вагнера 29 О Дирака 31 О Кнута — Бендикса — Уэ 843 О Крушкаля — Наша — Виллиамса 850 О Кука 1022 О Куратовского 29 О Кэли 87 О Маклейна 29, 353 О Метивиера 851 О Ньюмена 842 О о неподвижной точке 956 О Оре 31 О Оттера 89 О Понтрягина — Куратовского 352 0 Рида 87 О Скойнса 87 О Татта 31'374 О Харари — Принса 90 О Харари — Палмера 89 О Харари — Принса — Татта 91 О Хватала 31 О Хехта 957 О Чена 165 О Шмитта 844 О Эйлера 29, 353 Теорема: О Касьянова 267 О Хехта — Ульмана 269 Терм 819 О конвергентный 841 О нередуцируемый 841 О редуцируемый 841 О тупиковый 841 О унифицируемый 820 Терминал 536 Тест случайности для пар 1070 Тип 643 Толщина 371 Топологическая сортировка 189 О обратная 189 Точка равновесия 1063 Точное покрытие 3-множествами 1048 О ограниченное 1047 Транзитивная редукция 200, 947 О вершины 203 Транзитивное замыкание: О бинарного отношения 198 0 графа 199 Трансдуктор 533 Транслятор: 0 back-end 641 О front-end 641 О вторичный 641 О первичный 641 Трехмерное сочетание 1048 О для множества, совместимого по парам 1049 0 с ограничениями по весу 1049 Триангуляция: 0 плоская 353 0 с ограничением 1045 Тупик 595 0 семантический 596 У Уграф 258 0 (интервально) несводимый 267 0 (интервально) сводимый 267 0 г-производный 266 0 взвешенный 284 0 обобщенно сводимый 269 0 предельный 266 0 разборный 273 0 регуляризуемый 269 0 сводимый по Хехту и Ульману 273 0 спиральный 312 Удаление: 0 дублирующих переменных: ° нетерминальных 916 ° терминальных 916 0 избыточных проверок 916 0 мертвого кода 663 0 общих подвыражений 662 0 петли 272 Указатель 892 Укладка 96, 189, 1025 0 плоская 352 0 сильная 311 0 слабая 311 Унификатор 224, 820 0 множества уравнений 820 0 мультиуравнения 822 0 наибольший общий 820 Унификация: 0 длин ребер 338 0 для конечно определенных алгебр 1063 0 ограниченная для конечно определенных алгебр 1062 0 ограниченная с коммутативными операциями 1063
Предметный указатель 1103 О с коммутативными операциями 1064 0 сгибов 338 Уничтожение 1061 Упаковка 1049 0 3-множеств 1049 0 в контейнеры 1052 0 в фиксированное число контейнеров 1052 Упорядочение: 0 ациклическое 312 0 линейное 848 0 мультимножеств 850 0 редукционное 849 0 рекурсивных путей 850 0 циклическое 1070 Упорядоченное исключение для орграфа 1038 Уравнение 820 0 Веллмана 44 Условие: 0 возрастающих цепей 944 0 убывающих цепей 944 ° обрыва 803 Утверждение 899 Участок: 0 линейный 260 0 повторяемости 300 0 циклический 301 Ф Фаза: 0 анализа 641 0 синтеза 641 Фактор-граф по множеству бикомпонент 244 Факторизация 801 Фактор-уграф 264 Фильтр 957, 1061 Формула Эйлера 29 Фрагмент 259 0 главный 399 О основной 399 0 первичный 261 0 правильный 261 0 простой 261 0 элементарный 399 Функция: 0 антиизотонная 946 0 антимонотонная 805 0 быстрая 806 ° по Кэму — Ульману 806 0 ВЕРХ 295 0 дистрибутивная 805 0 кратности 974 0 меток 407 0 монотонная 805, 945 0 оценочная 778 0 помечающая 982 0 расширенного потока 809 0 скорая по Розену 808 0 типа 407 0 эффекта: ° дуги 794 ° пути 794 ц Центр 339 Цепочка 535 0 вложенная 299 0 внешняя 299 0 выводимая 537 0 выполнения 877 0 замкнутая 298 0 непосредственно вложенная 299 0 простая 298 0 пустая 535 Цепь 43, 943 0 к-ограниченная, 806 0 к-полуограниченная, 806 Цикл 25, 43, 187 0 внутренний 667 0 гамильтоновый 30 0 грани 374 0 позвоночный 354 0 порожденный 1034 ч Часть: О графа 26 0 общая 822 Число: 0 вершинной связности 23 0 доминирующих множеств 1035 0 несоответствия нумерации 272 0 реберной связности 25 0 скрещиваний 371 0 хроматическое 38 0 цикломатическое 780 Чу-множества: 0 изоморфные 946 0 расширение 946 0 реализация 946 0 самодвойственные 946
1104 Предметный указатель ш Шашки на доске n х n 1062 Шенноново разложение 923 Шина 364 Ширина 1038 0 дерева 1038 0 корневого ордерева 1038 0 орграфа 1038 0 разбиения 384 0 чу-множества 946 Шкала 1024 э Экванионалы 1ая: 0 спецификация 838 0 эквациональная теория 838 ° разрешимая 844 Экономная расклейка уграфа 281 Эксцентриситет 32 Элемент 22 0 входной 973 0 выходной 974 0 наибольший 944 0 наименьший 944 0 несравнимый 944 0 сети 973 0 сравнимый 944 Элиминация переменной 821 Этапы трансляции 532 Я Ядро 1038 Язык 536 0 допускаемый МП-распознавателем 552 0 неоднозначный 541 0 определяемый МП-распознавателем 552 О определяемый распознавателем 544 0 префиксный 982 0 свободный 975 0 свободный терминальный 982 Терминальный 982 Яркость 340 О входные уровни 341 п гистограмма 341 0 измерение 361 * * * Х-алгебра 839 vy-исвязь 895 6-приближение 351