I am using the Boost graph to store a set of nodes and edges and then write it to a graphml format. Whatever I do, I cannot find a way to access or set the node id (n0, n1) or edge id (e0) attributes. It seems to be automatically set.
Is there a way to access and set it manually ?
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="canonical" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n1">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n0" target="n1">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
My graph
typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
GpNode, GpEdge>
DirectedGraph;
Where GpNode and GpEdge are custom class definitions.
Thanks in advance
write_graphml
takes a dynamic_properties
. Let's configure that:
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphml.hpp>
struct GpNode {
int id;
std::string name;
bool station;
double theta;
double x;
double y;
};
struct GpEdge {
double length;
double max_speed;
std::string name;
int source;
int target;
};
using DirectedGraph = boost::adjacency_list<boost::vecS, boost::vecS,
boost::directedS, GpNode, GpEdge>;
int main() {
std::ifstream ifs("input.xml");
DirectedGraph g;
auto n0 = add_vertex(
GpNode{
10000, // id
"node1", // name
0, // station
0, // theta
6.95279e-310, // x
0, // y
}, g);
auto n1 = add_vertex(
GpNode{
10001, // id
"node1", // name
0, // station
0, // theta
6.95279e-310, // x
0, // y
}, g);
/*auto e0 = */add_edge(n0, n1,
GpEdge{
6.95279e-310, // length
150, // max_speed
"", // name
-127787376, // source
21994, // target
}, g);
auto vindex = get(&GpNode::id, g);
boost::dynamic_properties dp;
//dp.property("node_id", vindex);
dp.property("id", vindex);
dp.property("name", get(&GpNode::name, g));
dp.property("station", get(&GpNode::station, g));
dp.property("theta", get(&GpNode::theta, g));
dp.property("x", get(&GpNode::x, g));
dp.property("y", get(&GpNode::y, g));
dp.property("length", get(&GpEdge::length, g));
dp.property("max_speed", get(&GpEdge::max_speed, g));
dp.property("name", get(&GpEdge::name, g));
dp.property("source", get(&GpEdge::source, g));
dp.property("target", get(&GpEdge::target, g));
boost::write_graphml(std::cout, g, dp);
}
Prints
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n1">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n0" target="n1">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
Mmm. That took a while. But now I see. I know that write_graphviz_dp
assumes node_id
is the node id property, but as you can see, I tried and it didn't help
But, wait, docs show a second overload that also takes VertexIndexMap. Let's.... try that?
boost::write_graphml(std::cout, g, vindex, dp);
Now it prints
<?xml version="1.0" encoding="UTF-8"?>
<graphml xmlns="http://graphml.graphdrawing.org/xmlns" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
<key id="key0" for="node" attr.name="id" attr.type="int" />
<key id="key1" for="edge" attr.name="length" attr.type="double" />
<key id="key2" for="edge" attr.name="max_speed" attr.type="double" />
<key id="key3" for="node" attr.name="name" attr.type="string" />
<key id="key4" for="edge" attr.name="name" attr.type="string" />
<key id="key5" for="edge" attr.name="source" attr.type="int" />
<key id="key6" for="node" attr.name="station" attr.type="boolean" />
<key id="key7" for="edge" attr.name="target" attr.type="int" />
<key id="key8" for="node" attr.name="theta" attr.type="double" />
<key id="key9" for="node" attr.name="x" attr.type="double" />
<key id="key10" for="node" attr.name="y" attr.type="double" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n10000">
<data key="key0">10000</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<node id="n10001">
<data key="key0">10001</data>
<data key="key3">node1</data>
<data key="key6">0</data>
<data key="key8">0</data>
<data key="key9">6.95279e-310</data>
<data key="key10">0</data>
</node>
<edge id="e0" source="n10000" target="n10001">
<data key="key1">6.95279e-310</data>
<data key="key2">150</data>
<data key="key4"></data>
<data key="key5">-127787376</data>
<data key="key7">21994</data>
</edge>
</graph>
</graphml>
That's likely as close as you'll get with it. Changing the id
type to std::string
doesn't prevent the "n"
prefix. (I suppose it's to allow edges to have id's colliding with nodes without problems?)