Różnice między wybraną wersją a wersją aktualną.
Both sides previous revision Previous revision Next revision | Previous revision | ||
graph_import_export [2009/04/10 11:47] sgasioro |
graph_import_export [2009/04/10 12:53] (aktualna) sgasioro |
||
---|---|---|---|
Linia 34: | Linia 34: | ||
Wczytywanie różnych grafów, np. z plików znalezionych w internecie, wymaga określenia różnych parametrów, co w praktyce wiąże się z zajrzeniem do pliku z grafem i ręczne określenie np. co jest głownym identyfikatorem węzła lub jakie każdy węzeł lub krawędź ma właściwości (np. "name", "color", "weight"). Nie ma jednej funkcji do wczytania dowolnego grafu, a przynajmniej nie ma takiej opisanej w dokumentacji. Jest to z góry narzucone przez niefortunny sposób opisu grafów w tych bibliotekach, który zakłada, że atrybuty grafu będą znane podczas kompilacji. | Wczytywanie różnych grafów, np. z plików znalezionych w internecie, wymaga określenia różnych parametrów, co w praktyce wiąże się z zajrzeniem do pliku z grafem i ręczne określenie np. co jest głownym identyfikatorem węzła lub jakie każdy węzeł lub krawędź ma właściwości (np. "name", "color", "weight"). Nie ma jednej funkcji do wczytania dowolnego grafu, a przynajmniej nie ma takiej opisanej w dokumentacji. Jest to z góry narzucone przez niefortunny sposób opisu grafów w tych bibliotekach, który zakłada, że atrybuty grafu będą znane podczas kompilacji. | ||
Jest to wielka wada, gdyż praktycznie uniemożliwia wykorzystanie tej biblioteki do wczytywania grafów stworzonych przez innych. | Jest to wielka wada, gdyż praktycznie uniemożliwia wykorzystanie tej biblioteki do wczytywania grafów stworzonych przez innych. | ||
+ | |||
+ | ====== Przykład ====== | ||
+ | |||
+ | <code cpp> | ||
+ | #include <iostream> | ||
+ | #include <string> | ||
+ | #include <boost/graph/graphml.hpp> | ||
+ | |||
+ | using namespace std; | ||
+ | using namespace boost; | ||
+ | |||
+ | // definiujemy typ grafu | ||
+ | typedef adjacency_list< vecS, vecS, directedS, | ||
+ | property< vertex_name_t, string >, | ||
+ | property< edge_weight_t, int > | ||
+ | > Graph; | ||
+ | |||
+ | void CreateGraph(Graph &g, dynamic_properties &dp) | ||
+ | { | ||
+ | // nazwy wierzcholkow | ||
+ | const char* name[] = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" }; | ||
+ | |||
+ | // definiujemy typ krawedzi | ||
+ | typedef std::pair<int,int> Edge; | ||
+ | |||
+ | // tworzymy krawedzie grafu | ||
+ | Edge my_edges[] = { | ||
+ | Edge(0, 1), | ||
+ | Edge(1, 2), Edge(1, 5), Edge(1, 8), | ||
+ | Edge(2, 3), | ||
+ | Edge(3, 2), Edge(3, 4), Edge(3, 6), | ||
+ | Edge(6, 7), | ||
+ | Edge(7, 8), | ||
+ | Edge(8, 7), | ||
+ | Edge(9, 10), | ||
+ | Edge(10, 9) | ||
+ | }; | ||
+ | |||
+ | // tworzymy wagi odpowienich krawedzi | ||
+ | int my_wages[] = { | ||
+ | 4, | ||
+ | 2, 1, 5, | ||
+ | 3, | ||
+ | 3, 1, 2, | ||
+ | 9, | ||
+ | 2, | ||
+ | 2, | ||
+ | 6, | ||
+ | 6 | ||
+ | }; | ||
+ | |||
+ | // ilosc krawedzi | ||
+ | const int nedges = sizeof(my_edges)/sizeof(Edge); | ||
+ | |||
+ | // tworzymy graf z wierzcholkow | ||
+ | g = Graph(my_edges, my_edges + nedges, 10); | ||
+ | |||
+ | // ustawiamy wartosci wierzcholkow (tutaj np. stringi) | ||
+ | graph_traits<Graph>::vertex_iterator v, v_end; | ||
+ | for (tie(v,v_end) = vertices(g); v != v_end; ++v) | ||
+ | put(vertex_name_t(), g, *v, name[*v]); | ||
+ | |||
+ | // ustawiamy wagi krawedzi | ||
+ | graph_traits<Graph>::edge_iterator e, e_end; | ||
+ | int index = 0; | ||
+ | for (tie(e,e_end) = edges(g); e != e_end; ++e, ++index) | ||
+ | put(edge_weight_t(), g, *e, my_wages[index]); | ||
+ | |||
+ | // ustawiamy, ze wierzcholki beda mialy pole name a krawedzie weight | ||
+ | dp.property("name", get(vertex_name_t(), g)); | ||
+ | dp.property("weight", get(edge_weight_t(), g)); | ||
+ | } | ||
+ | |||
+ | void SaveGraphML(Graph &g, dynamic_properties &dp, const char *filename) | ||
+ | { | ||
+ | ofstream ofile(filename); | ||
+ | |||
+ | // skladnia: | ||
+ | //void write_graphml(std::ostream& out, const Graph& g, const dynamic_properties& dp, | ||
+ | // bool ordered_vertices=false) | ||
+ | |||
+ | // zapis do strumienia | ||
+ | write_graphml(ofile, g, dp, true); | ||
+ | |||
+ | ofile.close(); | ||
+ | } | ||
+ | |||
+ | void LoadGraphML(Graph &g, dynamic_properties &dp, const char *filename) | ||
+ | { | ||
+ | ifstream ifile(filename); | ||
+ | |||
+ | // musimy dodac wlasnosci recznie | ||
+ | dp.property("name", get(vertex_name_t(), g)); | ||
+ | dp.property("weight", get(edge_weight_t(), g)); | ||
+ | |||
+ | // lapiemy mozliwe wyjatki | ||
+ | try | ||
+ | { | ||
+ | read_graphml(ifile, g, dp); | ||
+ | } | ||
+ | catch (bad_parallel_edge &ge) | ||
+ | { | ||
+ | cout << "bad_parallel_edge from " << ge.from << " to " << ge.to << endl; | ||
+ | } | ||
+ | catch (directed_graph_error&) | ||
+ | { | ||
+ | cout << "directed_graph_error" << endl; | ||
+ | } | ||
+ | catch (undirected_graph_error&) | ||
+ | { | ||
+ | cout << "undirected_graph_error" << endl; | ||
+ | } | ||
+ | catch (parse_error&) | ||
+ | { | ||
+ | cout << "parse_error" << endl; | ||
+ | } | ||
+ | catch (property_not_found &ge) | ||
+ | { | ||
+ | cout << "property_not_found " << ge.property << endl; | ||
+ | } | ||
+ | |||
+ | ifile.close(); | ||
+ | } | ||
+ | |||
+ | void SaveGraphVIZ(Graph &g, dynamic_properties &dp, const char *filename) | ||
+ | { | ||
+ | ofstream ofile(filename); | ||
+ | |||
+ | // zapis do strumienia, "name" jako identyfikator wezla | ||
+ | write_graphviz(ofile, g, dp, string("name")); | ||
+ | |||
+ | ofile.close(); | ||
+ | } | ||
+ | |||
+ | void LoadGraphVIZ(Graph &g, dynamic_properties &dp, const char *filename) | ||
+ | { | ||
+ | ifstream ifile(filename); | ||
+ | |||
+ | // nalezy recznie dodac wlasnosci | ||
+ | dp.property("name", get(vertex_name_t(), g)); | ||
+ | dp.property("weight", get(edge_weight_t(), g)); | ||
+ | |||
+ | // skladnia: | ||
+ | // bool read_graphviz(std::istream& in, MutableGraph& graph, | ||
+ | // dynamic_properties& dp, | ||
+ | // std::string const& node_id = "node_id") | ||
+ | |||
+ | // lapiemy mozliwe wyjatki | ||
+ | try | ||
+ | { | ||
+ | // odczyt ze strumienia, "name" jako identyfikator wezla | ||
+ | read_graphviz(ifile, g, dp, "name"); | ||
+ | } | ||
+ | catch (bad_parallel_edge &ge) | ||
+ | { | ||
+ | cout << "bad_parallel_edge from " << ge.from << " to " << ge.to << endl; | ||
+ | } | ||
+ | catch (directed_graph_error&) | ||
+ | { | ||
+ | cout << "directed_graph_error" << endl; | ||
+ | } | ||
+ | catch (undirected_graph_error&) | ||
+ | { | ||
+ | cout << "undirected_graph_error" << endl; | ||
+ | } | ||
+ | catch (parse_error&) | ||
+ | { | ||
+ | cout << "parse_error" << endl; | ||
+ | } | ||
+ | catch (property_not_found &ge) | ||
+ | { | ||
+ | cout << "property_not_found " << ge.property << endl; | ||
+ | } | ||
+ | |||
+ | ifile.close(); | ||
+ | } | ||
+ | |||
+ | void CheckGraphs(Graph &g1, Graph &g2) | ||
+ | { | ||
+ | assert(num_vertices(g2) == num_vertices(g1)); | ||
+ | assert(num_edges(g2) == num_edges(g1)); | ||
+ | |||
+ | graph_traits<Graph>::vertex_iterator v, v_end; | ||
+ | for (tie(v,v_end) = vertices(g1); v != v_end; ++v) | ||
+ | assert(get(vertex_name_t(), g1, *v) == get(vertex_name_t(), g2, *v)); | ||
+ | |||
+ | graph_traits<Graph>::edge_iterator e, e_end; | ||
+ | for (tie(e,e_end) = edges(g1); e != e_end; ++e) | ||
+ | assert(get(edge_weight_t(), g1, *e) == get(edge_weight_t(), g2, *e)); | ||
+ | } | ||
+ | |||
+ | int main(int argc, char *argv[]) | ||
+ | { | ||
+ | Graph g; | ||
+ | dynamic_properties dp; | ||
+ | CreateGraph(g, dp); | ||
+ | |||
+ | // zapisujemy graph do pliku | ||
+ | SaveGraphML(g, dp, "graph.xml"); | ||
+ | |||
+ | // odczytujemy nowy graf | ||
+ | Graph g2; | ||
+ | dynamic_properties dp2; | ||
+ | LoadGraphML(g2, dp2, "graph.xml"); | ||
+ | |||
+ | // sprawdzenie czy dobrze zostalo zapisane i wczytane | ||
+ | CheckGraphs(g, g2); | ||
+ | |||
+ | // -------------------------------------------------- | ||
+ | |||
+ | // zapisujemy graph do pliku | ||
+ | SaveGraphVIZ(g, dp, "graph_viz.dot"); | ||
+ | |||
+ | Graph g3; | ||
+ | dynamic_properties dp3; | ||
+ | LoadGraphVIZ(g3, dp3, "graph_viz.dot"); | ||
+ | |||
+ | // sprawdzenie czy dobrze zostalo zapisane i wczytane | ||
+ | CheckGraphs(g, g3); | ||
+ | |||
+ | // wypisujemy na ekran | ||
+ | write_graphml(cout, g3, dp3, true); | ||
+ | |||
+ | return 0; | ||
+ | } | ||
+ | </code> | ||
+ | |||
+ | |||
+ | Graf użyty w przykładzie w kodzie:\\ | ||
+ | {{:graf1.gif|}} | ||
+ |