Система Orphus

C++ Boost Graph Library

Авторы: Джереми Сик
Лай-Кван Ли
Эндрю Ламсдэйн
Издательство: Питер, 2006
304 страницы

Материал предоставил: Алексей Кирюшкин
Найти в магазинах
Купить в Озоне (306 руб.)
Купить в Books.Ru
Купить в Болеро (273 руб.)
Купить в издательстве "Питер"
Купить в OZ.by (Беларусь)
Купить в My-Shop.ru (276 руб.)

Аннотация

Содержание
Предисловие
Введение
Комментарии

Аннотация

Издание, являющееся переводом одной из книг серии "C++ in Depth", посвящено описанию Boost Graph Library (BGL) - библиотеки для построения структур данных и алгоритмов вычислений на графах, предназначенных для решения самых разнообразных задач: от оптимизации интернет-маршрутизации и планирования телефонных сетей до задач молекулярной биологии. Содержит развернутое описание BGL, демонстрирует примеры приложений к реальным задачам.

Первая часть является полным руководством пользователя, начинается с введения понятий теории графов, терминологии и описания обобщенных алгоритмов на графах, знакомит пользователя со всеми основными возможностями библиотеки BGL. Вторая часть - полное справочное руководство, содержит документацию ко всем концепциям BGL, ее алгоритмам и классам.

Содержание

Предисловие
Введение
Обобщенное программирование
Немного из истории BGL
Что такое Boost?
Получение и установка программного обеспечения BGL
Как пользоваться книгой
Грамотное программирование
Благодарности
Лицензия
От издательства

Часть I. Руководство пользователя

Глава 1. Введение

1.1. Немного терминологии из теории графов
1.2. Графовые концепции
1.2.1. Описатели вершин и ребер
1.2.2. Отображение свойств
1.2.3. Обход графа
1.2.4. Создание и модификация графа
1.2.5. Посетители алгоритмов
1.3. Классы и адаптеры графов
1.3.1. Классы графов
1.3.2. Адаптеры графов
1.4. Обобщенные алгоритмы на графах
1.4.1. Обобщенный алгоритм топологической сортировки
1.4.2. Обобщенный алгоритм поиска в глубину

Глава 2. Обобщенное программирование в C++

2.1. Введение
2.1.1. Полиморфизм в объектно-ориентированном программировании
2.1.2. Полиморфизм в обобщенном программировании
2.1.3. Сравнение ОП и ООП
2.2. Обобщенное программирование и STL
2.3. Концепции и модели
2.3.1. Наборы требований
2.3.2. Пример: InputIterator
2.4. Ассоциированные типы и классы свойств
2.4.1. Ассоциированные типы в шаблонах функций
2.4.2. Определители типов, вложенные в классах
2.4.3. Определение класса свойств
2.4.4. Частичная специализация
2.4.5. Диспетчеризация тегов
2.5. Проверка концепции
2.5.1. Классы для проверки концепций
2.5.2. Прототипы концепций
2.6. Пространство имен
2.6.1. Классы
2.6.2. Поиск Кенига
2.7. Именованные параметры функций

Глава 3. Изучаем BGL

3.1. Зависимости между файлами
3.2. Подготовка графа
3.2.1. Решаем, какой графовый класс использовать
3.2.2. Строим граф с помощью итераторов ребер
3.3. Порядок компиляции
3.3.1. Топологическая сортировка через поиск в глубину
3.3.2. Маркировка вершин с использованием внешних свойств
3.3.3. Доступ к смежным вершинам
3.3.4. Обход всех вершин
3.4. Циклические зависимости
3.5. ''На пути'' к обобщенному поиску в глубину: посетители
3.6. Подготовка графа: внутренние свойства
3.7. Время компиляции
3.8. Обобщенная топологическая сортировка и поиск в глубину
3.9. Время параллельной компиляции
3.10. Итоги

Глава 4. Основные алгоритмы на графах

4.1. Поиск в ширину
4.1.1. Определения
4.1.2. Шесть степеней Кевина Бэкона
4.2. Поиск в глубину
4.2.1. Определения
4.2.2. Нахождение циклов в графах потоков управления программы

Глава 5. Задачи нахождения кратчайших путей

5.1. Определения
5.2. Маршрутизация в Интернете
5.3. Алгоритм Беллмана-Форда и маршрутизация с помощью вектора расстояний
5.4. Маршрутизация с учетом состояния линии и алгоритм Дейкстры

Глава 6. Задача минимального остовного дерева

6.1. Определения
6.2. Планирование телефонной сети
6.3. Алгоритм Краскала
6.4. Алгоритм Прима

Глава 7. Компоненты связности

7.1. Определения
7.2. Связные компоненты и связность Интернета
7.3. Сильные компоненты связности и ссылки веб-страниц

Глава 8. Максимальный поток

8.1. Определения
8.2. Реберная связность

Глава 9. Неявные графы: обход конем

9.1. Ходы конем как граф
9.2. Поиск с возвратом на графе
9.3. Эвристика Варнсдорфа

Глава 10. Взаимодействие с другими графовыми библиотеками

10.1. Использование топологической сортировки из BGL с графом из LEDA
10.2. Использование топологической сортировки из BGL с графом из SGB
10.3. Реализация адаптеров графов

Глава 11. Руководство по производительности

11.1. Сравнения графовых классов
11.1.1. Результаты и обсуждение
11.2. Итоги главы

Часть II. Справочное руководство

Глава 12. Концепции BGL

12.1. Концепции обхода графов
12.1.1. Неориентированные графы
12.1.2. Graph
12.1.3. IncidenceGraph
12.1.4. BidirectionalGraph
12.1.5. AdjacencyGraph
12.1.6. VertexListGraph
12.1.7. EdgeListGraph
12.1.8. AdjacencyMatrix
12.2. Концепции для изменения графов
12.2.1. VertexMutableGraph
12.2.2. EdgeMutableGraph
12.2.3. MutableIncidenceGraph
12.2.4. MutableBidirectionalGraph
12.2.5. MutableEdgeListGraph
12.2.6. PropertyGraph
12.2.7. VertexMutablePropertyGraph
12.2.8. EdgeMutablePropertyGraph
12.3. Концепции посетителей
12.3.1. BFSVisitor
12.3.2. DFSVisitor
12.3.3. DijkstraVisitor
12.3.4. BellmanFordVisitor

Глава 13. Алгоритмы BGL

13.1. Обзор
13.1.1. Информация об алгоритме
13.2. Базовые алгоритмы
13.2.1. breadth_first_search
13.2.2. breadth_first_visit
13.2.3. depth_first_search
13.2.4. depth_first_visit
13.2.5. topological_sort
13.3. Алгоритмы кратчайших путей
13.3.1. dijkstra_shortest_paths
13.3.2. bellman_ford_shortest_paths
13.3.3. johnson_all_pairs_shortest_paths
13.4. Алгоритмы минимальных остовных деревьев
13.4.1. kruskal_minimum_spanning_tree
13.4.2. prim_minimum_spanning_tree
13.5. Статические компоненты связности
13.5.1. connected_components
13.5.2. strong_components
13.6. Растущие компоненты связности
13.6.1. initialize_incremental_components
13.6.2. incremental_components
13.6.3. same_component
13.6.4. component_index
13.7. Алгоритмы максимального потока
13.7.1. edmunds_karp_max_flow
13.7.2. push_relabel_max_flow

Глава 14. Классы BGL

14.1. Классы графов
14.1.1. adjacency_list
14.1.2. adjacency_matrix
14.2. Вспомогательные классы
14.2.1. graph_traits
14.2.2. adjacency_list_traits
14.2.3. adjacency_matrix_traits
14.2.4. property_map
14.2.5. property
14.3. Графовые адаптеры
14.3.1. edge_list
14.3.2. reverse_graph
14.3.3. filtered_graph
14.3.4. Указатель на SGB Graph
14.3.5. GRAPH<V,E> из библиотеки LEDA
14.3.6. std::vector<EdgeList>

Глава 15. Библиотека отображений свойств

15.1. Концепции отображений свойств
15.1.1. ReadablePropertyMap
15.1.2. WritablePropertyMap
15.1.3. ReadWritePropertyMap
15.1.4. LvaluePropertyMap
15.2. Классы отображений свойств
15.2.1. property_traits
15.2.2. iterator_property_map
15.2.3. Теги свойств
15.3. Создание пользовательских отображений свойств
15.3.1. Отображения свойств для Stanford GraphBase
15.3.2. Отображение свойств из std::map

Глава 16. Вспомогательные концепции, классы и функции

16.1. Buffer
16.2. ColorValue
16.3. MultiPassInputIterator
16.4. Monoid
16.5. mutable_queue
16.6. Непересекающиеся множества
16.6.1. disjoint_sets
16.6.2. find_with_path_halving
16.6.3. find_with_fullpath_compression
16.7. tie
16.8. graph_property_iter_range

Библиография
Дополнение к библиографии
Теория графов
C++ и STL
Алфавитный указатель

Предисловие

Александр Степанов

Когда я впервые увидел эту книгу, я почувствовал зависть. В конце концов желание создать библиотеку, подобную Boost Graph Library (BGL), привело меня к открытию обобщенного программирования. В 1984 году я вошел в профессорско-преподавательский состав Политехнического университета в Бруклине, имея некоторые, еще довольно смутные, идеи построения библиотек программных компонентов. По правде говоря, они были на втором плане: в то время мои истинные интересы касались формальных обоснований естественного языка, кое в чем напоминающего Органона Аристотеля, но более полного и формального. Я был, наверное, единственным доцентом на кафедрах информатики и электротехники, кто собирался получить должность, внимательно изучая категории Аристотеля. Интересно заметить, что дизайн Standard Template Library (STL), в частности лежащий в основе онтологии объектов, базируется на моем понимании того, что отношение "целое-часть" является основополагающим отношением, которое описывает реальный мир, и что оно вообще не похоже на отношение "элемент-множество", известное нам из теории множеств. Реальные объекты не имеют общих частей: моя нога не является еще чьей-то ногой. То же самое можно сказать и о контейнерах STL. Например операции std::list::spliсе перемещают части из одного контейнера в другой подобно операции по пересадке органов: моя почка - это моя почка, до тех пор, пока ее не пересадят кому-нибудь другому.

В любом случае, я был твердо убежден, что программные компоненты должны быть функциональными и основываться на системе функционального программирования Джона Бэкуса (John Backus's FP system). Единственной новой идеей было то, что функции могут быть связаны с некоторыми аксиомами. Например, "алгоритм русского крестьянина", позволяющий вычислить n-ю степень за O(log n) шагов, подходит для любого объекта, для которого определена бинарная ассоциативная операция. Другими словами, я верил, что алгоритмы должны быть связаны с тем, что сейчас мы называем концепциями (см. раздел 2.3 этой книги), которые я обозначал как структурные типы (structure types), а теоретики называют многосортными алгебрами (multi-sorted algebras).

Удачей для меня было то, что в Политехническом университете был замечательный человек - Аарон Кершенбаум, обладавший глубокими знаниями в области алгоритмов на графах и стремлением их реализовать. Аарон заинтересовался моими попытками расчленить программы на простые примитивы и провел много времени, обучая меня графовым алгоритмам и работая со мной над их реализацией. Он также показал мне, что есть фундаментальные вещи, которые нельзя сделать в функциональном стиле без высоких изменений в сложности. Хотя я часто мог реализовать алгоритмы, требующие линейного времени, в функциональном стиле без изменения асимптотической сложности, реализовать на практике алгоритмы с логарифмическим временем без изменения сложности на линейную я не мог. В частности, Аарон объяснял мне, почему очередь по приоритетам столь важна для алгоритмов на графах. Он был хорошо осведомлен в этом вопросе: Кнут в его книге по Stanford GraphBase [22] приписывает авторство Аарону в применении частично упорядоченных бинарных деревьев (binary heaps) к алгоритмам Прима и Дейкстры. Мы очень обрадовались, когда смогли получить алгоритмы Прима и Дейкстры как два случая одного обобщенного алгоритма (высокоуровневого). Это просто замечательно, что код BGL схож с нашим кодом (см. например сноску в разделе 13.4.2). Следующий пример на языке Scheme показывает, как два алгоритма были реализованы в терминах одного высокоуровневого алгоритма. Единственная разница заключается в том, как комбинируются значения расстояний: сложением у Дейкстры и выбором второго операнда у Прима:

(define dijkstra
(make-scan-based-algorithm-with-mark 
  make-heap-with-membership-and-values + < ))

(define prim
(make-scan-based-algorithm-with-mark 
  make-heap-with-membership-and-values (lambda (x у) у) < ))

На поиск подходящего языка программирования для эффективной реализации подобного стиля у меня ушло почти десять лет. Наконец я нашел C++, который помог мне создавать программы, полезные для общества. Более того, C++ серьезно повлиял на мой проект, основанный на модели машины для С. Шаблоны и перегрузка функций - вот особенности C++, позволившие создать STL.

Я часто слышу от людей выражения недовольства по поводу перегрузки в C++, но, как это обычно бывает для большинства полезных механизмов, перегрузка может быть использована неправильно. Для разработки полезных абстракций перегрузка незаменима. Если мы обратимся к математике, то многие ее идеи получили развитие именно благодаря перегрузке. В качестве примера можно привести расширение понятия чисел от натуральных к целым, к рациональным, к гауссовым, к p-адическим числам и т. д. Можно легко догадаться о некоторых вещах без знания точных определений. Если я вижу выражение, в котором используются операции сложения и умножения, я предполагаю наличие дистрибутивности. Если я вижу знак "меньше" и сложение, то предполагаю, что если а < Ь, то а+с < Ь+с (я редко складываю несчетные количества). Перегрузка позволяет нам переносить знание от одного типа к другому.

Важно понять, что можно писать обобщенные алгоритмы, просто используя перегрузку, без шаблонов, но это требует много нажатий на клавиши. То есть для каждого класса, например удовлетворяющего требованиям итератора произвольного доступа, нужно вручную определять все относящиеся к нему алгоритмы. Это утомительно, но осуществимо (нужно определять только сигнатуры: тела будут те же). Нужно заметить, что настраиваемые модули (generics) в языке Ада требуют ручной реализации и, поэтому, не так полезны, поскольку каждый алгоритм нужно реализовывать вручную. Шаблоны C++ решают эту проблему, позволяя определять такие вещи единожды.

Еще есть вещи, нужные в обобщенном программировании, но непредставимые в C++. Обобщенные алгоритмы - это алгоритмы, которые работают с объектами, обладающими похожими интерфейсами. Не идентичными, как в объектно-ориентированном программировании, а именно похожими. Использование не только бинарных методов вызывает проблему (см. раздел 2.1.3), интерфейсы фактически описываются с помощью одного типа (односортная алгебра). Если мы внимательно посмотрим на объекты вроде итераторов, то увидим, что они могут быть описаны только в терминах нескольких типов: тип самого итератора, тип значения и тип расстояния. Другими словами, необходимо три типа, чтобы определить интерфейсы для одного типа. В C++ для этого нет нужного аппарата. В результате мы не можем определить итераторы и, следовательно, откомпилировать обобщенные алгоритмы. Например, если мы определим алгоритм reduce таким образом:

template <class InputIterator, class BinaryOperationWithIdentity> 
typename iterator_traits<InputIterator>::value_type 
reduce(InputIterator first, InputIterator last, 
       BinaryOperationWithIdentity op)
{
  typedef typename iterator_traits<InputIterator>::value_type T; 
  if (first == last) return identity_element(op); 
  T result = *first;
  while (++first != last) result = op(result, *first); 
  return result;
}

но вместо ++first != last напишем ++first < last, никакой компилятор не сможет обнаружить ошибку в месте определения. Хотя стандарт ясно декларирует, что operator< не нужен для итераторов ввода, у компилятора нет возможности знать об этом. Требования к итераторам сформулированы только на словах. Мы пытаемся программировать с концепциями (многосортными алгебрами) на языке, в котором для них нет поддержки.

Насколько сложно расширить C++, чтобы действительно позволить этот стиль программирования? Во-первых, нам нужно ввести концепции как новое средство интерфейса. Например, мы можем определить следующие концепции:

concept SemiRegular : Assignable, DefaultConstructible {}; 
concept Regular : SemiRegular, EqualityComparable {}: 
concept InputIterator : Regular,  Incrementable {
  SemiRegular value_type;
  Integral distance_type:
  const value_type& operator*(); 
}:

value_type(InputIterator)
reduce(InputIterator first, InputIterator last,
       BinaryOperationWithIdentity op) 
(value_type(InputIterator) == argument_type(BinaryOperationWithIdentity))
{
  if (first == last) return identity_element(op);
  value_type(InputIterator) result = *first; 
  while (++first != last) result = op(result, *first); 
  return result;
}

Обобщенные функции (generic functions) - это функции, которые принимают концепции как аргументы и в добавление к списку аргументов имеют список ограничений типов. Теперь полная проверка типов может быть выполнена в месте определения, без рассмотрения мест вызова или в местах вызова без рассмотрения тела алгоритма.

Иногда требуется несколько реализаций одной и той же концепции. Например, для слияния возможна следующая запись:

Outputlterator merge(InputIterator[l] first1, InputIterator[l] last1, 
                     InputIterator[2] first2, InputIterator[2] last2,
                     OutputIterator result)
(bool operator<(value_type(InputIterator [1]), value_type(InputIterator [2])),
value_type(InputIterator[1]) == value_type(InputIterator[2]),
output_type(OutputIterator) == value_type(InputIterator[2]));

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

В языке C++ поддерживается два различных механизма абстракции: объектно-ориентированный подход и шаблоны. Использование объектно-ориентированного подхода позволяет точно определить интерфейс и провести диспетчеризацию времени исполнения. Вместе с этим диспетчеризация бинарных или мультиметодов неосуществима, а связывание времени исполнения часто неэффективно. Шаблоны предназначены для более сложных интерфейсов и разрешены во время компиляции. Серьезным препятствием для их использования разработчиками программного обеспечения является тот факт, что в шаблонах отсутствует разделение между интерфейсами и реализацией. Например, недавно я пытался откомпилировать пример STL-программы из десяти строк, используя один из наиболее популярных компиляторов C++... Я был в шоке, увидев несколько страниц неразборчивых сообщений об ошибках. Можно предположить, что введение концепций объединит возможности обоих подходов и уберет ограничения, накладываемые ими. Кроме того, можно представить концепции в виде виртуальных таблиц, распространяющихся на указатели к описателям типов: виртуальная таблица для итератора ввода содержит не только указатели на operator* и operator++, но и указатели на актуальный тип итератора, тип его значения и тип расстояния. А затем можно ввести указатели и ссылки на концепции!

Обобщенное программирование - это сравнительно молодое направление в программировании. Я счастлив наблюдать, что небольшая попытка, начатая двадцать лет назад Дэйвом Массером, Дипаком Капуром, Аароном Кершенбаумом и мной, привела к появлению библиотек нового поколения, таких как BGL и MTL. Я должен поздравить Университет Индианы с лучшей командой по обобщенному программированию в мире. Я уверен, что они сотворят и другие чудеса!

Введение

Джереми Сик и др.

Графовая абстракция - это мощный инструмент решения задач, используемый для описания отношений между - дискретными объектами. Практические задачи могут быть смоделированы в виде графов для различных областей, например таких, как маршрутизация пакетов в Интернете, проектирование телефонной сети, системы сборки программного обеспечения, поисковые машины WWW, молекулярная биология, системы автоматизированного планирования дорожного маршрута, научные вычисления и т. п. Достоинством графовой абстракции является тот факт, что найденное решение проблемы теории графов может быть использовано для решения проблем в широком диапазоне областей. Например, задача нахождения выхода из лабиринта и задача нахождения групп взаимно достижимых веб-страниц могут быть решены с помощью поиска в глубину - важнейшего положения из теории графов. При сосредоточении на сути этих задач, а именно на графовой модели, описывающей дискретные объекты и отношения между ними, специалисты по теории графов нашли решения не просто для "горстки" отдельных проблем, а для целых семейств задач.

Сразу же возникает вопрос. Если теория графов всеобще и широко применяется для произвольных сфер задач, не должно ли программное обеспечение, реализующее графовые алгоритмы, быть таким же универсальным в применении? Может показаться, что теория графов - это идеальная область для повторного использования программного кода. Однако до сих пор потенциальное повторное использование было далеко от реальности. Графовые задачи редко встречаются в чистой теоретико-графовой форме, они чаще включены в более крупные проблемы, зависящие от области применения. В результате данные, которые можно смоделировать как граф, зачастую явно не представлены как граф, и тогда они закладываются в некоторую структуру данных, специфичную для приложения. Даже в случае, когда данные приложения явно представлены в виде графа, конкретное представление, выбираемое программистом, может не совпадать с представлением, ожидаемым библиотекой. Более того, различные приложения могут накладывать разные ограничения к временной и пространственной сложности графовых структур данных.

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

Обобщенное программирование

Стандартная библиотека шаблонов (Standard Template Library, STL) [40] появилась в 1994 году и была сразу принята в стандарт C++. STL - библиотека взаимозаменяемых компонентов для решения многих фундаментальных задач на последовательностях элементов. Отличие библиотеки STL от предлагаемых ранее библиотек состоит в том, что каждый STL-алгоритм может работать с широким набором последовательных структур данных: связные списки, массивы, множества и т. п. Абстракция итератора обеспечила интерфейс между контейнерами и алгоритмами, и шаблонный механизм C++ предоставил нужную гибкость в реализации без потери эффективности. Каждый алгоритм в STL является шаблоном функции, параметризованным по типам итераторов, с которыми он работает. Любой итератор, который удовлетворяет минимальному набору требований, может быть использован независимо от структуры данных, обходимой итератором. Системный подход, использованный в STL для построения абстракций и взаимозаменяемых компонентов, называется обобщенным программированием.

Обобщенное программирование хорошо зарекомендовало себя при решении проблемы повторного использования кода для библиотек алгоритмов на графах. В рамках обобщенного программирования алгоритмы на графах могут быть сделаны более гибкими и легко используемыми в большом наборе приложений. Каждый графовый алгоритм пишется не в терминах специфической структуры данных, а для графовой абстракции, которая может быть реализована многими различными структурами данных. Написание обобщенных графовых алгоритмов имеет дополнительное преимущество, являясь более естественным. Абстракция, свойственная псевдокоду описания алгоритма, сохраняется в обобщенной функции.

Библиотека Boost Graph Library (BGL) - это первая библиотека графов C++, применяющая понятия обобщенного программирования при создании алгоритмов на графах.

Немного из истории BGL

Boost Graph Library появилась как библиотека обобщенных графовых компонентов (Generic Graph Component Library, GGCL) в лаборатории научных вычислений (Lab for Scientific Computing, LSC). Эта лаборатория под руководством профессора Эндрю Ламсдэйна охватывала различные сферы деятельности, занималась исследованиями алгоритмов, программного обеспечения, инструментов и систем времени выполнения для вычислительной науки и техники. Особое внимание было уделено разработке промышленного, высокопроизводительного программного обеспечения с использованием современных языков программирования и методов, в том числе обобщенного программирования.

Вскоре после того как была выпущена STL, в LSC началась работа по применению обобщенного программирования к научным расчетам. Библиотека матричных шаблонов (Matrix Template Library, MTL) была одним из первых проектов. Многие уроки, усвоенные во время создания MTL, были учтены при проектировании и реализации GGCL.

Одним из важных классов вычислений линейной алгебры в научных расчетах является класс вычислений с разреженными матрицами, в котором графовые алгоритмы играют большую роль. Когда лаборатория LSC разрабатывала методы обработки разреженных матриц для MTL, необходимость в высокопроизводительных повторно используемых (и обобщенных) графовых алгоритмах стала очевидна. Однако ни в одной из графовых библиотек, доступных в то время (LEDA, GTL, Stanford GraphBase), не использовался обобщенный стиль программирования в отличие от STL или MTL. Таким образом, данные библиотеки не удовлетворяли требованиям LSC в гибкости и производительности. Другие исследователи также были заинтересованы в создании обобщенной библиотеки алгоритмов на графах для C++. Во время встречи с Бьерном Страуструпом мы познакомились с некоторыми людьми из "AT&T", тоже нуждавшимися в такой библиотеке. Другая ранняя работа в области графовых алгоритмов включала отдельные примеры кодов, написанных Александром Степановым, а также Дитмаром Кюлем в его магистерской диссертации.

Джереми Сик, вдохновленный домашними упражнениями по алгоритмам для своего курса, начал создавать прототипы интерфейса и некоторых графовых классов весной 1998 года с учетом более ранних разработок. Затем Лай-Кван Ли разработал первую версию GGCL, которая стала его магистерским диссертационным проектом.

В следующем году авторы начали сотрудничать с Александром Степановым и Мэтью Остерном. В это время реализация Степанова для компонент связности на основе непересекающихся множеств была добавлена к GGCL, и началась работа по документированию концепций для GGCL подобно документации Остерна для STL.

В том же году авторам стало известно о Boost, и они были обрадованы тем, что нашли организацию, заинтересованную в создании высококачественных библиотек C++ с открытыми исходными кодами. В Boost было несколько человек, уделявших внимание обобщенным графовым алгоритмам, и одним из этих людей был Дитмар Кюль. Некоторые обсуждения обобщенных интерфейсов для графовых структур привели к пересмотру GGCL и появлению в ней новых интерфейсов, очень похожих на те, что есть в Boost Graph Library сейчас.

4 сентября 2000 года GGCL была формально рецензирована под руководством Дэвида Абрахамса и стала Boost Graph Library. Первый выпуск BGL состоялся 27 сентября 2000 года. BGL не является "замороженной" библиотекой. Она продолжает расти и развиваться для наибольшего удовлетворения потребностей своих пользователей. Мы приглашаем читателей присоединиться к группе Boost для работы над расширением BGL.

Комментарии

Алексей Кирюшкин

Лёд тронулся, господа присяжные заседатели :) Вышла первая книга по библиотекам Boost на русском языке. И это хорошо, и это правильно - ну сколько программистов использовало бы сейчас MFC, если бы она не расписывалась в каждой второй книге по програмимированию на C++? Правильно - столько же сколько сейчас используют Boost. Так что пробуем первый блин и ждем следующий - Beyond the C++ Standard Library: An Introduction to Boost.

Ах, да, слова благодарности и замеченные нескладушки не забываем адресовать научному редактору перевода - LaptevVV