Пользоваться Сетевой библиотекой Библиотеки/Узла Графика или Записать Мое Собственное?

Как это:

#Item1
#:Somestuff
#Item2
18
задан Catskul 7 October 2009 в 18:49
поделиться

8 ответов

Возможно, я смогу дать небольшое руководство по BGL.

Библиотека очень гибкая. Цена этого в том, что синтаксис может быть очень причудливым, чтобы учесть все возможности. Тем не менее, он достаточно гибкий, чтобы простые вещи можно было делать просто.

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

( «Любая достаточно продвинутая технология неотличима от магии» - Артур Кларк. Он должен был сказать следующее: «Любая продвинутая технология, достаточно плохо задокументированная, неотличима от магии»

Подумайте:

typedef property_map<Graph, vertex_index_t>::type IndexMap;
IndexMap index = get(vertex_index, g);
typedef graph_traits<Graph>::vertex_iterator vertex_iter;
std::pair<vertex_iter, vertex_iter> vp;
for (vp = vertices(g); vp.first != vp.second; ++vp.first) {
   std::cout << index[*vp.first] <<  " ";
}

Вот как тур "предлагает распечатать список вершин графа. Однако небольшое исследование показывает, что вершина - это не более чем целочисленный индекс, и код можно значительно упростить до

for (int v = *vertices(g).first; v != *vertices(g).second; ++v)
    std::cout << v << " ";

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

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

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

и код можно значительно упростить до

for (int v = *vertices(g).first; v != *vertices(g).second; ++v)
    std::cout << v << " ";

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

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

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

и код можно значительно упростить до

for (int v = *vertices(g).first; v != *vertices(g).second; ++v)
    std::cout << v << " ";

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

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

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

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

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

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

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

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

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

Затем я обычно использую небольшую служебную функцию, чтобы инкапсулировать сложность и держать ее подальше от алгоритма, над которым я работаю.

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

Затем я обычно использую небольшую служебную функцию, чтобы инкапсулировать сложность и держать ее подальше от алгоритма, над которым я работаю.

Например, мне часто нужно перебирать дочерние элементы вершины

vector<int> getVertexChildren( int v )
{
    vector<int> vc;
    typedef std::pair<graph_traits<graph_t>::out_edge_iterator, graph_traits<graph_t>::out_edge_iterator> out_edge_iter_pair_t;
    for( out_edge_iter_pair_t ep = out_edges(v,m_tree);
        ep.first != ep.second; ++(ep.first))
    {
        vc.push_back( target( *ep.first, m_tree ) );
    }
    return vc;
}
#define FOR_ALL_CHILDREN( v ) vector<int> vc=getVertexChildren(v); BOOST_FOR_EACH( int child, vc )

Суть в следующем: go вперед и используйте BGL. Его можно упростить, чтобы делать простые вещи, но как только вы научитесь его использовать, вся огромная гибкость будет доступна, когда вам это нужно.

28
ответ дан 30 November 2019 в 05:49
поделиться

Я думаю, что если вы можете использовать алгоритмы обхода графа, то стоит использовать Boost Graph. Создавать и использовать собственные вершины довольно просто. Примеры, включенные в BGL, были полезны для изучения того, как его использовать.

Я согласен с Клиффордом, я использовал GraphViz для визуализации графика во время разработки и нашел его очень полезным.

6
ответ дан 30 November 2019 в 05:49
поделиться

Недавно я испытал библиотеку графов ускорений для определения кратчайшего пути Дейкстра. проблема. Результаты:

  • Очень высокая производительность

  • Требуется очень мало кода

  • Очень гибкий и расширяемый

  • Трудно понять или отладить

Совет: Используйте его , но перед этим read Библиотека графов ускорения: руководство пользователя и справочное руководство

9
ответ дан 30 November 2019 в 05:49
поделиться

«требует значительных изменений в структуре классов узла и / или ребер».

Вы смотрели на функцию «связанных свойств» в BGL?

http: //www.boost.org/doc/libs/1_40_0/libs/graph/doc/bundles.html

Это одновременно мощный и немаловажный элемент.

Вы определяете классы для своих ребер и вершин

class cMyVertex
{
…
};
class cMyEdge
{
…
};

Теперь вы определяете тип графа, который будет использовать ваши классы.

typedef boost::adjacency_list<
    boost::listS, boost::vecS, boost::bidirectionalS,
    cMyVertex, cMyEdge > graph_t;

Теперь вы можете создавать графы этого типа, которые будут использовать ваши классы, какими бы они ни были, для вершин и ребер.

Вы можете получить доступ к атрибутам и методы ваших классов совершенно естественным образом

Graph_t g(10)       // create a graph with 10 vertices
g[1].setA1( “alpha” );  // invoke an accessor on node #1
10
ответ дан 30 November 2019 в 05:49
поделиться

Вы также можете попробовать использовать графическую библиотеку LEMON .

Я мог бы использовать ее для поиска кратчайшего пути Dijsktra после чтения графа из файла конфигурации.

Только что вышла новая версия.

5
ответ дан 30 November 2019 в 05:49
поделиться

Это действительно не краткий ответ, это скорее дополнение к тому, что уже было сказано.

Решение этой проблемы зависит от контекста проблемы. Если вы хотите лучше понять, как работают алгоритмы графов и программное обеспечение. Напишите свой. Если вы хотите получить глубокие знания об алгоритмах и структурах графов или реализовать их в своей собственной программе, изучите стандартную библиотеку графов. (См. Причины использования повторно используемого кода)

Лучшее из обоих миров. Сделайте и то, и другое. Если вы растягиваете время, возьмите книгу по этому поводу или следуйте руководствам и примерам.

Другое предложение: задайте новый острый вопрос о том, какая {лучшая, самая надежная, самая легкая в изучении} библиотека графов для {описания очень общей проблемы}? Это поможет вам выбрать, чему учиться, вместо того, чтобы пытаться наугад найти наиболее подходящий вариант. Кто-то уже видел эту проблему, спросите совета.

Использование повторно используемого кода:

  1. Код, написанный кем-то другим, включая тестовые примеры, обычно будет более надежным, чем ваш собственный.
  2. Исправления легче внедрить (с обновлениями компонента, который вы повторно используете), это правда в Boost (поскольку они делают частые обновления, и этот Boost проверяется коллегами).
  3. Как только вы изучите одну структуру, вы можете применить ее к другим приложениям ... кто знает, что вы можете получить работу позже в жизни, используя эту структуру. Компании любят повторно использовать велосипед, а не изобретать его.
4
ответ дан 30 November 2019 в 05:49
поделиться

Я накатил свой собственный. Вам не следует следовать этому примеру, если вы не абсолютно уверены, что вам это нужно.

Тем не менее, это отличный учебный опыт, если вы знаете, что теория графов заржавела.

Мне было очень «весело» с объединением орграфов с использованием операторов EBNF и выполнения исключения эпсилона и минимизации на основе Хопкрофта. Особенно с минимизацией, если вы можете отчаянно звонить, пытаясь найти хорошую информацию и выяснить, как она работает "весело": - (

Если вы все-таки откатите свой собственный, Я рекомендую отделить высокоуровневые операции от низкоуровневых структур данных орграфа - разные классы, а не только разные методы. Я этого не сделал - и довольно скоро я буду сильно заниматься рефакторингом из-за этого плохого решения.

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

Кроме того, иногда вы просто хотите работать с вещами, которые не были явно разработаны как орграф IYSWIM - например, набор узлов структуры данных, которые связаны друг с другом.

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

ИМО, я понял когда я написал класс «древовидного инструмента», который выполняет такие вещи, как итерация и индексирование в древовидном порядке и порядке тегов XML-элементов. Базовое древовидное представление является подключаемым (шаблон на основе политики). С орграфами я напортачил.

В любом случае, я не знаю, что на самом деле предоставляет Boost или какая-либо другая библиотека графов, но если она предоставляет то, что вам нужно, я говорю, используйте ее. Это избавит от головной боли.

IMO Я понял это правильно, когда написал класс «древовидного инструмента», который выполняет такие вещи, как итерация и индексирование в древовидном порядке и порядке тегов элементов XML. Базовое древовидное представление является подключаемым (шаблон на основе политики). С орграфами я напортачил.

В любом случае, я не знаю, что на самом деле предоставляет Boost или какая-либо другая библиотека графов, но если она предоставляет то, что вам нужно, я говорю, используйте ее. Это избавит от головной боли.

IMO Я понял это правильно, когда написал класс «древовидного инструмента», который выполняет такие вещи, как итерация и индексирование в древовидном порядке и порядке тегов элементов XML. Базовое древовидное представление является подключаемым (шаблон на основе политики). С орграфами я напортачил.

В любом случае, я не знаю, что на самом деле предоставляет Boost или какая-либо другая библиотека графов, но если она предоставляет то, что вам нужно, я говорю, используйте ее. Это избавит от головной боли.

3
ответ дан 30 November 2019 в 05:49
поделиться

Прежде чем принять решение о создании собственной библиотеки графов, я хотел бы хорошенько взглянуть на igraph ( http://igraph.sourceforge.net/ ). Он написан на C, работает очень быстро и предлагает более широкий спектр базовых и расширенных алгоритмов графов (включая визуализацию). Кроме того, он имеет оболочку python для быстрого кодирования, поэтому я думаю, что это решение сочетает в себе скорость кодирования и скорость выполнения.

3
ответ дан 30 November 2019 в 05:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: