如何设置 C++ boost graphml 节点和边 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 是自定义类定义

提前致谢

解决方法

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,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,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" 前缀。 (我想这是为了让边缘可以毫无问题地与节点碰撞?)