I still have a problem getting graph properties written to a graphml file (vertex and edge properties get written just fine). Following Jeremiah's advise form two weeks ago I implemented the code below. The problem appears to be that the instance of ref_property_map contained in the dynamic_properties uses the key type Graph*, but the write_graphml function implemented in boost/graph/graphml.hpp expects it to be of type Graph. This of course results in a different typeid and the write_graphml function does not recognize the entry in the dynamic properties as graph properties. I tried to change the key type of ref_property_map to Graph, which resulted in a compilation error. Any insight in how to solve that problem would be greatly appreciated! Here is my current code: #include <boost/graph/graph_traits.hpp> #include <boost/graph/adjacency_list.hpp> #include <boost/graph/graphml.hpp> struct VertexProperties { std::string strName; }; struct EdgeProperties { std::string strName; }; struct GraphProperties { std::string strName; }; std::ostream& operator<< (std::ostream& strm, const VertexProperties& p) { strm << p.strName; return strm; } std::istream& operator>> (std::istream& strm, VertexProperties& p) { strm >> p.strName; return strm; } std::ostream& operator<< (std::ostream& strm, const EdgeProperties& p) { strm << p.strName; return strm; } std::istream& operator>> (std::istream& strm, EdgeProperties& p) { strm >> p.strName; return strm; } std::ostream& operator<< (std::ostream& strm, const GraphProperties& p) { strm << p.strName; return strm; } std::istream& operator>> (std::istream& strm, GraphProperties& p) { strm >> p.strName; return strm; } typedef boost::property<boost::vertex_name_t, VertexProperties> vertex_p; typedef boost::property<boost::edge_weight_t, EdgeProperties> edge_p; typedef boost::property<boost::graph_name_t, GraphProperties> graph_p; typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, vertex_p, edge_p, graph_p> Graph; typedef boost::graph_traits<Graph>::vertex_descriptor vertex_t; typedef boost::graph_traits<Graph>::edge_descriptor edge_t; typedef boost::property_map<Graph, boost::vertex_name_t>::type vertex_prop_t; typedef boost::property_map<Graph, boost::edge_weight_t>::type edge_prop_t; typedef boost::ref_property_map<Graph*, GraphProperties> graph_propt_t; int main() { //-- create a graph: Graph g; vertex_t u = boost::add_vertex(g); vertex_t v = boost::add_vertex(g); edge_t e; bool b; boost::tie(e,b) = boost::add_edge(u,v,g); //-- get the property maps: vertex_prop_t vertexPropMap = boost::get(boost::vertex_name, g); edge_prop_t edgePropMap = get(boost::edge_weight, g); GraphProperties& graphProp = boost::get_property(g, boost::graph_name); //-- set some vertex, edge, and graph properties: vertexPropMap[u].strName = "first vertex"; vertexPropMap[v].strName = "second vertex"; edgePropMap[e].strName = "an edge"; graphProp.strName = "the graph"; //-- create dynamic property map: boost::dynamic_properties dp(boost::ignore_other_properties); dp.property("vertex_properties", vertexPropMap); dp.property("edge_properties", edgePropMap); graph_propt_t graphPropMap(graphProp); dp.property("graph_properties", graphPropMap); //-- write graphml to file: std::ofstream graphmlOutFile("graph.xml"); boost::write_graphml(graphmlOutFile, g, dp, true); graphmlOutFile.close(); return 0; } On Thu, 1 Mar 2012, Jeremiah Willcock wrote:
On Tue, 28 Feb 2012, Juerg Tschirren wrote:
I wrote the code below to construct a directed graph with internal properties (for vertices, edges, and the graph itself) and write everything to a graphml file. The code compiles and works as it is, but my two questions are:
1. What dynamic property do I have to add to write the graph properties out to the graphml file as well? So far I could only figure out how to write vertex and edge properties.
You should be able to add a graph property like in the following code (from libs/graph/test/graphviz_test.cpp):
boost::ref_property_map<graph_t*,std::string> gname( get_property(graph,graph_name)); dp.property("name",gname);
2. Does everything else look good? Specifically, is it O.K. to define the properties the way I did in the first typedef line (without using boost::property<>), and is it O.K. to access the properties the way I do it?
It will work, but a better way would be to use boost::property or a class containing your string which you can then access using g[v].mem or g[e].mem.
-- Jeremiah Willcock