2009-09-30 5 views
16

Ich versuche mich zu entscheiden, ob ich mit einer vorgefertigten Graphen/Knoten-Netzwerkbibliothek arbeiten oder meine eigene rollen soll.Verwenden Sie eine Graph Library/Node Network Library oder schreiben Sie mein eigenes?

Ich implementiere einige Graph-Suchalgorithmen, die eine wesentliche Anpassung an die Klassenstruktur des Knotens und/oder der Kanten erfordern.

Der Grund, warum ich nicht sicher bin, was ich tun soll, ist, dass ich nicht sicher bin, ob die Anpassung eines Pre-made teurer/problematischer ist, als mein eigenes zu machen. Ich bin auch neugierig, aber weniger auf die Performance-Kompromisse.

Gibt es jemanden da draußen, der direkte Erfahrungen mit der Verwendung einer der Bibliotheken dort draußen hat und auf einer Erfolgs- oder Misserfolgsgeschichte basiert? Ich möchte das Schlimmste hören, so dass ich, egal was ich wähle, weiß, worauf ich hinauswill.

Es gibt nur zwei, die ich bisher in meiner Suche gefunden habe: The Boost Graph Library (BGL) und GOBLIN. Spezifischer Rat zu beiden oder Vorschläge für andere werden ebenfalls sehr geschätzt. BGL scheint ziemlich verdächtig zu sein. Lohnt es sich zu kämpfen?

+3

Boost für seine Qualität allgemein bekannt, und die BGL-Schnittstellen mit GraphViz. – Clifford

+0

@Clifford hat Recht - unterschätzen Sie nicht die Fähigkeit, GraphViz zu nutzen - es ist absolut erstaunlich. – DaveParillo

Antwort

24

Ich kann vielleicht ein wenig Anleitung für die BGL bieten.

Die Bibliothek ist sehr flexibel. Der Preis dafür ist, dass die Syntax sehr barock sein kann, um alle Möglichkeiten unterzubringen. Es ist jedoch ausreichend flexibel, dass einfache Dinge einfach erledigt werden können.

Leider geht die Boost-Dokumentation in Sachen Vollgas und bietet nur eine Beschreibung der ganzen Komplexität, ohne einen Hinweis darauf, wie einfach Dinge sein können.

(. „Jede hinreichend fortschrittliche Technologie von Magie nicht zu unterscheiden ist“ - Arthur C. Clarke Was er gesagt haben sollte „Jede hinreichend fortschrittliche Technologie ist schlecht dokumentiert, nicht von Magie)

Bedenken Sie:

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

Dies ist, wie die „Quick-Tour“, schlägt wir eine Liste der Eckpunkte Diagramm ausdrucken. Allerdings ein wenig Studie zeigt, dass ein Scheitelpunkt als ein integer-Index nicht mehr ist, und der Code kann stark zu

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

Vielleicht gibt es einige magische Dinge, die mit diesem vereinfachten Code nicht erreicht werden können, aber für jeden Tag ist es sinnvoll, die Syntax, die BGL inkrustiert, drastisch zu beschneiden, damit Sie sehen können, was Sie codieren.

Manchmal kann die ausgefeilte Syntax nicht entfernt werden. (Oder vielleicht habe ich gerade die zugrunde liegende Wahrheit nicht bemerkt). Dann benutze ich normalerweise eine kleine Hilfsfunktion, um die Komplexität zu kapseln und sie von dem Algorithmus, an dem ich arbeite, fernzuhalten.

Zum Beispiel, ich muss oft eine Schleife über die Kinder eines Scheitels

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) 

Unterm Strich ist: gehen Sie voran und BGL verwenden. Es kann vereinfacht werden, einfache Dinge zu tun, aber sobald Sie gelernt haben, es zu verwenden, wird die ganze immense Flexibilität verfügbar sein, wann immer Sie es brauchen.

+0

Welche Erfahrung haben Sie beim Debuggen? Ich habe die Befürchtung, dass das Debugging mit BTL ein Albtraum sein könnte. – Catskul

+0

Haben Sie auch versucht, neue Funktionen dafür zu schreiben? Ich schaue mir zum Beispiel dijkstra_shortest_paths.hpp an und bin erstaunt, wie arkan es ist:/ – Catskul

+2

Debugging ist schwieriger als selbst gebrauter Code. Mein Debugger (MSVS2008) kann nicht in die von BGL verwendeten tiefen Datenstrukturen eindringen. Sie erhalten jedoch viel weniger Fehler als beim Hausbrauen. Ich habe keine neue Funktionalität zu BGL hinzugefügt. – ravenspoint

5

Ich denke, wenn Sie die Graph Traversal-Algorithmen nutzen können, lohnt es sich, die Boost Graph zu verwenden. Das Erstellen und Verwenden von benutzerdefinierten Scheitelpunkten ist ziemlich einfach. Die in BGL enthaltenen Beispiele waren hilfreich, um zu lernen, wie man sie benutzt.

Ich stimme mit Clifford überein, ich habe GraphViz verwendet, um die Grafik während der Entwicklung zu visualisieren und fand es sehr nützlich.

+0

Ich bin neugierig, wofür verwenden Sie BGL? Sind Sie auf Probleme gestoßen? Ich ziehe es vor, das Schlimmste zu hören, selbst wenn ich etwas wähle, damit ich weiß, worauf ich hinauswill. – Catskul

8

„erfordern eine signifikante Anpassung an die Klassenstruktur des Knotens und/oder Kanten.“

Haben Sie sich auf der „gebündelten Eigenschaften“ Merkmal des BGL?

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

Dies ist leistungsfähig und kein bisschen acrcane.

Sie definieren eine Klasse für Ihre Kanten und Ihre Ecken

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

Sie nun einen Diagrammtyp definieren, die Ihre Klassen

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

Jetzt können Sie grafische Darstellungen dieser Art erstellen verwenden, die verwenden Ihre Klassen, was auch immer sie sind, für die Ecken und Kanten.

Sie können die Attribute und Methoden der Klassen in einer ganz natürliche Art und Weise Zugang

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

+1 für den Hinweis auf gebündelte Eigenschaften - sie erleichtern wirklich viele Dinge für viele häufige Anwendungsfälle. –

3

ich meine eigenen gerollt. Sie sollten diesem Beispiel nicht folgen, es sei denn, Sie sind absolut sicher, dass Sie das müssen.

Dennoch ist es eine großartige Lernerfahrung, wenn Sie Graphentheorie ist rostig.

Ich hatte viel Spaß mit der Kombination von Digraphen mit EBNF-Operatoren, und tun epsilon Beseitigung und Hopcroft-basierte Minimierung. Vor allem mit der Minimierung, wenn Sie verzweifelt versuchen können, gute Informationen zu finden und herauszufinden, wie es "Spaß" funktioniert :-(

Wenn Sie Ihre eigene rollen, empfehle ich, High-Level-Operationen von den niedrigen Digraph Daten zu trennen Strukturen - verschiedene Klassen, nicht nur verschiedene Methoden.Ich habe nicht - und ziemlich bald werde ich stark wegen dieser schlechten Entscheidung refaktorieren.

Einige Graphen kommentieren Knoten, einige kommentieren Kanten, einige beides Manchmal sind zwei Anmerkungen nützlich, auch wenn sie nur Fremdschlüssel für einige externe Daten sind.Zum Beispiel in endlichen Automaten kann eine Kante mit einem Eingang und einemAusgang versehen werden.Sie sind wahrscheinlich am Determinismus interessiert WRT die Eingabe, aber nicht die Ausgabe , so dass sie beide hinter einer einzigen ID versteckt sind ein Schmerz - und das ist neben der ganzen Frage der Sekundärcontainer für die Was-ist-das-ID-Verweis-Lookups.

Manchmal möchten Sie auch nur mit Dingen arbeiten, die nicht explizit als Digraph IYSWIM entworfen wurden - z. eine Reihe von Datenstrukturknoten, die miteinander verknüpft sind.

IOW, es ist nützlich, in der Lage zu sein, verschiedene Digraph-Darstellungen anzuschließen, aber immer noch die gleichen High-Level-Tools für viele Operationen verwenden.

IMO Ich habe es richtig gemacht, als ich eine "Baumwerkzeug" -Klasse schrieb, die Dinge wie Iterieren und Subskribieren in Baumansichtsreihenfolge und XML-Element-Tag-Reihenfolge ausführt.Die zugrunde liegende Baumdarstellung ist steckbar (richtlinienbasierte Vorlage). Mit Digraphen habe ich es vermasselt.

Wie auch immer, ich weiß nicht, was Boost oder irgendeine andere Grafikbibliothek tatsächlich bietet, aber wenn es das bietet, was Sie brauchen, sage ich es. Es wird eine Menge Kopfschmerzen sparen.

5

Sie können auch versuchen, mit LEMON Grafikbibliothek zu versuchen.

Ich könnte es zu Dijsktra kürzesten Pfadsuche nach dem Lesen des Diagramms aus einer Konfigurationsdatei durchführen.

Eine neue Version ist gerade herausgekommen.

+0

Ich zweite der Vorschlag von LEMON. Ich habe es heute getestet und bin beeindruckt von dem sauberen API-Design und den guten Optionen für verschiedene Graph-Implementierungen. dynamische Graphen vs. statische usw. Ich habe es bis jetzt auf 1 Million Knoten und 100 Millionen Kanten skaliert, ohne Performance-Probleme usw. Schließlich wurde es kompiliert und Build-getestet sauber auf den drei Plattformen, die ich verwende (Solaris, Linux, und MacOS); immer schön zu sehen, wenn Open Source verwendet wird. ZITRONE ist keine Zitrone. ;-) –

3

Dies ist wirklich keine knappe Antwort, es ist mehr zu dem, was bereits gesagt wurde hinzuzufügen.

Die Lösung für dieses Problem hängt vom Kontext des Problems ab. Wenn Sie ein gutes Verständnis dafür bekommen möchten, wie Graphalgorithmen und Software funktionieren. Schreibe dein Eigenes. Wenn Sie fortgeschrittene Kenntnisse über Graphalgorithmen und -strukturen erlangen oder diese in Ihr eigenes Programm implementieren wollen, dann lernen Sie eine Standardgraphenbibliothek. (Siehe die Gründe für die Verwendung von wiederverwendbarem Code)

Das Beste aus beiden Welten. Tue beides. Wenn Sie für die Zeit gestreckt sind, erhalten Sie ein Buch darüber oder folgen Sie den Anleitungen und den Beispielen.

Ein anderer Vorschlag: Stellen Sie eine neue spitzfindige Frage nach der {besten, zuverlässigsten, am einfachsten zu erlernenden} Grafikbibliothek für {beschreiben ein sehr allgemeines Problem}? Dies wird Ihnen helfen zu entscheiden, was Sie lernen sollen, anstatt nach dem Zufallsprinzip zu suchen, um das beste zu finden, das Ihren Bedürfnissen entspricht. Jemand hat dieses Problem bereits gesehen, um Rat gefragt.

Mehrweg Code:

  1. -Code, dass jemand anderes einschließlich Testfälle geschrieben hat, wird im Allgemeinen zuverlässig mehr als die eigene.
  2. Fixes sind einfacher zu implementieren (mit Updates für die Komponente, die Sie wiederverwenden), dies gilt in Boost (da sie häufige Updates durchführen, und dass Boost Peer-Review ist).
  3. Sobald Sie ein Framework lernen, können Sie das auf andere Anwendungen anwenden ... wer weiß, dass Sie später im Leben eine Arbeit mit dem Framework bekommen könnten. Unternehmen nutzen das Rad lieber neu als neu.
8

Ich gab vor kurzem die Boost-Graph-Bibliothek einen Versuch für Dijkstras kürzestes Pfadproblem. Ergebnisse:

  • Very High Performance

  • Sehr wenig Code benötigt

  • Sehr flexibel und erweiterbar

  • schwer zu verstehen oder zu debuggen

Hinweis: Uns e es aber bevor Sie lesen Sie dazuThe Boost Graph Library: User Guide and Reference Manual

+1

Nicht zu überraschend - es ist im Grunde die allgemeine Geschichte mit der C++ Standardbibliothek, die Boost erweitern möchte. – Steve314

+3

Ich würde sicherlich * nicht * zustimmen zu sagen, dass die STL schwer zu verstehen oder zu debuggen ist. Die STL selbst ist geradlinig, sehr gut definiert und sogar zum Debuggen geeignet. Boost :: Graph ist nicht. boost :: spirit (Parser-Bibliothek) noch schlimmer. –

+0

@REDSOFTADAIR: Zwei Fragen ... 1. Dieser Leitfaden und Handbuch ist von 2001. Das ist eine lange Zeit, und 3 Sprachen Standard-Updates vor. Ist es nicht ziemlich veraltet? Und - bedeutet das nicht, dass die BGL etwas veraltet ist? 2. Können Sie auf eine frei verfügbare Beschreibung des BGL auf hoher Ebene oder auf die Bewertung seiner Stärken und Schwächen, Designentscheidungen usw. zugreifen? – einpoklum

3

Vor der Entscheidung, Ihre eigene Graph Bibliothek zu bauen, würde ich einen guten Blick auf IGRAPH haben (http://igraph.sourceforge.net/).Es ist in C geschrieben und ist extrem schnell und bietet eine breitere Palette von grundlegenden und fortgeschrittenen Graphalgorithmen (einschließlich Visualisierung). Darüber hinaus hat es einen Python-Wrapper für schnelles Codieren, daher denke ich, dass diese Lösung die Geschwindigkeit des Codierens und die Geschwindigkeit der Ausführung kombiniert.

2

Ich benutze die BGL sehr, aber was mich mit BGL stört ist der Mangel an grundlegenden Algorithmen wie Edge und Vertex Connectivity, minimaler Kostenfluss und allgemeines maximales Gewicht perfektes Matching, nur um diejenigen zu nennen, die ich am meisten vermisse.

LEMON bietet all das und hat auch eine einfachere Syntax, was mich mit LEMON Probleme bei der Installation und Kompilierung auf WINDOWS Plattformen macht, aber ich werde wahrscheinlich trotz dieser Probleme zu LEMON wechseln.

+0

Gerade installiert es ... Habe VS2010 und neuste Smake ... alles lief reibungslos .... – ntg

Verwandte Themen