【问题标题】:How to set c++ boost graphml node and edge id?如何设置 c++ boost graphml 节点和边 ID?
【发布时间】:2021-06-13 22:22:27
【问题描述】:

我正在使用 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 是自定义类定义。

提前致谢

【问题讨论】:

  • 你的代码是什么?你期望什么价值观?您能否展示您的 GpNode/GpEdge 并告诉我们您想要什么生成的 XML?还是我误读了,您是否真的在尝试 /read/ 给定的 XML?简而言之,你能把你的问题说得更清楚吗?
  • 所以,我 painstakingly reverse engineered structs and graph initialization 来自您展示的 XML,只是在我查看之前进行复制。我想这可能会让我成为让人们使用Stack Overflow 作为“为我编写代码”服务的傻瓜。但是,我将假设您恰好拥有该代码,只是懒得包含它。请这样做,下一次,这将大大增加能够/愿意提供帮助的人数。

标签: c++ boost boost-graph


【解决方案1】:

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 与节点碰撞没有问题?)

【讨论】:

  • 旁注:我认为这个vertex_index 映射通常对所有 BGL 算法都有效。有些人特别要求它将顶点描述符映射到一个完整的域[0, num_vertices(g)) - 所以这会破坏合同。只是想你可能想知道这一点
  • 对于讨厌重复代码的人:30 LoC
  • 非常感谢您的详细解释,尽管我的问题不完整(菜鸟错误)。我应该分享我的完整代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-01
  • 1970-01-01
  • 1970-01-01
  • 2014-04-08
  • 1970-01-01
相关资源
最近更新 更多