如何设置 C++ boost graphml 节点和边缘 ID?

How to set c++ boost graphml node and edge id?

我正在使用 Boost 图存储一组节点和边,然后将其写入 graphml 格式。无论我做什么,我都找不到访问或设置节点 ID (n0, n1) 或边 ID (e0) 属性的方法。 好像是自动设置的。

有没有办法手动访问和设置它?

<?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>

我的图表


typedef typename boost::adjacency_list<boost::vecS, boost::vecS, boost::directedS,
                              GpNode, GpEdge>
    DirectedGraph;

其中 GpNode 和 GpEdge 是自定义 class 定义。

提前致谢

write_graphml需要一个dynamic_properties。让我们配置一下:

Live On Coliru

#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);
}

版画

<?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>

嗯。那花了一段时间。但现在我明白了。我知道 write_graphviz_dp 假定 node_id 是节点 ID 属性,但如您所见,我试过了但没有帮助

救援文件

但是,等等,文档显示了第二个重载,它也采用 VertexIndexMap。让我们......试试看?

boost::write_graphml(std::cout, g, vindex, dp);

现在打印

Live On Coliru

<?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>

这很可能与您将得到的一样接近。将 id 类型更改为 std::string 不会阻止 "n" 前缀。 (我猜是为了让边的id和节点碰撞没有问题吧?)