2009-09-30 13 views
16

Estoy tratando de decidir entre ir con una biblioteca de red de nodo/gráfico prefabricada o hacer mi propia versión.¿Usar una biblioteca de gráficos/biblioteca de red de nodos o escribir mi propia cuenta?

Estoy implementando algunos algoritmos de búsqueda de gráficos que pueden requerir una personalización significativa de la estructura de clases del nodo y/o bordes.

La razón por la que no estoy seguro de qué hacer es que no estoy seguro si la personalización de un prefabricado podría ser más costosa/problemática que hacer la mía en primer lugar. También siento curiosidad, pero no tanto, por las compensaciones de rendimiento.

¿Hay alguien por ahí que tenga experiencia directa en el uso de una de las bibliotecas y que tenga consejos basados ​​en una historia de éxito o fracaso? Quiero escuchar lo peor para que, sea lo que sea que elija, sé en lo que me estoy metiendo.

Sólo he encontrado dos en mi búsqueda hasta el momento: The Boost Graph Library (BGL) y GOBLIN. También se agradece mucho el asesoramiento específico sobre cualquiera de estos, o sugerencias para otros. BGL parece bastante malditamente arcano. ¿Vale la pena luchar?

+3

Boost conocido por su calidad en general, y las interfaces BGL con GraphViz. – Clifford

+0

@Clifford tiene razón, no subestime el poder de aprovechar GraphViz, es absolutamente increíble. – DaveParillo

Respuesta

24

Quizás pueda brindarle un poco de orientación sobre el BGL.

La biblioteca es muy flexible. El costo de esto es que la sintaxis puede ser muy barroca, para acomodar todas las posibilidades. Sin embargo, es lo suficientemente flexible como para hacer cosas simples de manera simple.

Lamentablemente, la documentación de impulso va a todo detalle, proporcionando una descripción solo de la complejidad total, sin una pista de lo simples que pueden ser las cosas.

(. "Cualquier tecnología suficientemente avanzada es indistinguible de la magia" - Arthur C. Clarke Lo que debería haber dicho es "Cualquier tecnología avanzada, lo suficientemente mal documentado, es indistinguible de la magia)

Considere:

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] << " "; 
} 

Así es como el "viaje rápido" sugiere que imprimir una lista de los vértices del gráfico. sin embargo, un pequeño estudio muestra que un vértice no es más que un índice de enteros, y el código se puede simplificar en gran medida a

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

Quizás haya algunas cosas mágicas que no se pueden lograr con este código simplificado, pero para cada día, utilícelas de forma razonable para reducir drásticamente la sintaxis que incrusta BGL para que pueda ver lo que está codificando.

A veces la sintaxis elaborada no se puede eliminar. (O tal vez no he notado la verdad subyacente). Entonces usualmente uso una pequeña función de utilidad para encapsular la complejidad y mantenerla alejada del algoritmo en el que estoy trabajando.

Por ejemplo, a menudo necesitan para recorrer los hijos de un vértice

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) 

La conclusión es: seguir adelante y utilizar BGL. Se puede simplificar para hacer cosas simples, pero una vez que haya aprendido a usarlo, toda la inmensa flexibilidad estará disponible siempre que lo necesite.

+0

¿Cuál es su experiencia en depurarlo? Temo que la depuración con BTL sea una pesadilla. – Catskul

+0

Además, ¿ha intentado escribir nuevas funcionalidades para ello? Estoy viendo dijkstra_shortest_paths.hpp como un ejemplo, y estoy asombrado de lo arisco que es:/ – Catskul

+2

La depuración es más difícil que el código elaborado en casa. Mi depurador (MSVS2008) no puede penetrar en las estructuras de datos profundas utilizadas por BGL. Sin embargo, obtienes muchos menos errores que con la cerveza casera. No he agregado una nueva funcionalidad a BGL. – ravenspoint

5

Creo que si puede aprovechar los algoritmos de cruce de gráficos, vale la pena usar el Boost Graph. Crear y usar vértices personalizados es bastante fácil. Los ejemplos incluidos con BGL fueron útiles para aprender a usarlo.

Estoy de acuerdo con Clifford, he utilizado GraphViz para ayudar a visualizar el gráfico durante el desarrollo y lo encontré muy útil.

+0

Tengo curiosidad, ¿para qué usa BGL? ¿Te has encontrado con algún problema? Prefiero escuchar lo peor incluso si voy a elegir algo para saber en qué me estoy metiendo. – Catskul

8

“requieren algún tipo de personalización significativa a la estructura de clases del nodo y/o bordes.”

¿Has mirado en la función de “propiedades liado” de la BGL?

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

Esto es a la vez potente y no acrcane lo más mínimo.

se define una clase para sus aristas y sus vértices

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

Ahora se define un tipo de gráfico que utilizará sus clases

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

Ahora puede crear gráficos de este tipo que va a utilizar tus clases, sean lo que sean, para los vértices y los bordes.

Se puede acceder a los atributos y métodos de sus clases de una manera perfectamente natural

Graph_t g(10)  // create a graph with 10 vertices 
g[1].setA1(“alpha”); // invoke an accessor on node #1 
+3

+1 para insinuar propiedades agrupadas: realmente facilitan mucho las cosas en muchos casos de uso común. –

3

Rodé mi propia. No debe seguir ese ejemplo, a menos que esté absolutamente seguro de que lo necesita.

Aún así, es una gran experiencia de aprendizaje, si su teoría de grafos está oxidada.

Me divertí mucho combinando dígrafos usando operadores EBNF, y haciendo eliminación de épsilon y minimización basada en Hopcroft. Especialmente con la minimización, si puede llamar desesperadamente tratando de encontrar buena información y descubrir cómo funciona "divertido" :-(

Si usted hace su propio rollo, le recomiendo separar las operaciones de alto nivel de los datos del dígrafo de bajo nivel estructuras - diferentes clases, no solo métodos diferentes. No lo hice - y muy pronto voy a refactorizar mucho debido a esa mala decisión.

Algunos gráficos anotan nodos, algunos anotan los bordes, algunos ambos. A veces dos anotaciones son útil, incluso si no son más que claves externas para algunos datos externos. Por ejemplo, en máquinas de estado finito, un borde puede ser anotado con una entrada y una salida. Es probable que esté interesado en el determinismo WRT la entrada pero no la salida , por lo que tener ambos escondidos detrás de una única ID es un problema, y ​​eso es además de todo el tema de los contenedores secundarios para las búsquedas what-do-this-ID-refer-to.

Además, a veces lo único que desea es trabajar con cosas que no fueron diseñadas explícitamente como un dígrafo IYSWIM - p. un grupo de nodos de estructura de datos que se vinculan entre sí.

IOW, es útil para poder enchufa diferentes representaciones de digrafos, y aún así usar las mismas herramientas de alto nivel para muchas operaciones.

IMO Lo hice bien cuando escribí una clase 'árbol herramienta' que hace cosas como iterar y subscribir en orden de vista de árbol y orden de etiqueta de elemento XML.La representación del árbol subyacente es conectable (plantilla basada en políticas). Con los dígrafos, lo eché a perder.

De todos modos, no sé lo que realmente ofrece Boost o cualquier otra biblioteca de gráficos, pero si proporciona lo que necesita, digo que lo use. Le ahorrará muchos dolores de cabeza.

5

También puedes probar con la biblioteca de gráficos LEMON.

Podría usarlo para realizar la búsqueda de ruta más corta de Dijsktra después de leer el gráfico de un archivo de configuración.

Acaba de salir una nueva versión.

+0

En segundo lugar la sugerencia de LIMÓN. Lo he estado probando hoy y estoy impresionado con el diseño API limpio y buenas opciones para diferentes implementaciones de gráficos; gráficos dinámicos vs estáticos, etc. Lo he escalado hasta 1 millón de nodos y 100 millones de bordes hasta el momento sin problemas de rendimiento, etc. Por último, compiló y compiló limpiamente en las tres plataformas que uso (Solaris, Linux, y MacOS); Siempre es agradable de ver cuando se usa código abierto. LIMÓN no es limón ;-) –

3

Esto realmente no es una respuesta concisa, es más de agregar a lo que ya se ha dicho.

La solución a este problema depende del contexto del problema. Si desea obtener una gran comprensión de cómo funcionan los algoritmos de gráficos y el software. Escribe lo tuyo. Si desea obtener un conocimiento avanzado de algoritmos y estructuras de gráficos o implementarlos en su propio programa, entonces aprenda una biblioteca de gráficos estándar. (Consulte las razones para usar un código reutilizable)

Lo mejor de ambos mundos. Haz ambos. Si tiene poco tiempo, obtenga un libro sobre esto o siga los tutoriales y los ejemplos.

Otra sugerencia: haga una nueva pregunta puntiaguda sobre la {mejor, más confiable, más fácil de aprender} biblioteca de gráficos para {describir un problema muy general}. Esto te ayudará a elegir qué aprender, en lugar de intentar al azar encontrar el mejor que se adapte a tus necesidades. Alguien ya ha visto este problema, pídele consejo.

El uso de código reutilizable:

  1. Código que alguien ha escrito que incluye casos de prueba generalmente será más fiable que el suyo propio.
  2. Las correcciones son más fáciles de implementar (con actualizaciones para el componente que está reutilizando), esto es cierto en Boost (ya que hacen actualizaciones frecuentes, y que Boost es revisado por pares).
  3. Una vez que aprende un marco, puede aplicarlo a otras aplicaciones ... quién sabe que puede obtener un trabajo más adelante en la vida utilizando el marco. A las empresas les gusta reutilizar en lugar de reinventar la rueda.
8

Hace poco dí una versión de prueba de la biblioteca de gráficos de impulso para el problema de la ruta más corta de Dijkstras. Resultados:

  • muy alto rendimiento

  • muy poco código necesario

  • muy flexible y extensible

  • difícil de entender o de depuración

Consejo: Nos e Se, pero antes de hacerlo leerThe Boost Graph Library: User Guide and Reference Manual

+1

No es demasiado sorprendente: básicamente es la historia general de la biblioteca estándar de C++ que Boost intenta ampliar. – Steve314

+3

Sin duda * no * estoy de acuerdo en decir que el STL es difícil de entender o depurar. El STL en sí es directo, muy bien definido e incluso razonable de depurar. boost :: graph no es. boost :: spirit (biblioteca de analizadores) aún peor. –

+0

@REDSOFTADAIR: Dos preguntas ... 1. Esa guía y el manual es de 2001. Hace mucho tiempo, y hace 3 actualizaciones estándar de idiomas. ¿No es bastante anticuado? Y, ¿no significa esto que BGL está un poco desactualizado? 2. ¿Puede vincular a alguna descripción de alto nivel libremente disponible del BGL, o una evaluación de sus fortalezas y debilidades, opciones de diseño, etc.? – einpoklum

3

Antes de decidirse a construir su propia biblioteca gráfica, me gustaría tener un buen vistazo a igraph (http://igraph.sourceforge.net/).Está escrito en C y es extremadamente rápido y ofrece una gama más amplia de algoritmos de gráficos básicos y avanzados (incluida la visualización). Además, tiene un contenedor de python para una codificación rápida, así que creo que esta solución combina velocidad de codificación y velocidad de ejecución.

2

Uso mucho el BGL, pero lo que me molesta con BGL es la falta de algoritmos básicos como conectividad de borde y vértice, flujo de costo mínimo y concordancia perfecta de peso máximo general, solo para nombrar los que más extraño.

LEMON ofrece todo eso y también tiene una sintaxis más simple, lo que me molesta con LEMON son los problemas de instalación y compilación en las plataformas WINDOWS, pero probablemente cambie a LEMON a pesar de esos problemas.

+0

Acabo de instalarlo ... Tengo VS2010 y lo último smake ... todo salió bien ... – ntg

Cuestiones relacionadas