如何在 boost 中正确使用捆绑属性?

How to properly use bundled properties in boost?

我正在尝试修改无向图中的特定顶点。本质上,我希望能够从 18 的索引 1 开始,并且 运行 一种算法可以从该顶点更改每个节点的字符串。我从一个点文件中读取了一张图表。我在 boost's website and it seem straight forward. However, when I try to implement this I get Attempt to put a value into a const property map: Aborted (core dumped) error. So I find this solution 查看 Bundled Properties,它看起来和我的一模一样。

这是引发错误的最小示例:

我正在阅读的文件 test.dot:

graph G {
0 [isLeaf=1];
1 [isLeaf=0];
2 [isLeaf=1];
3 [isLeaf=1];
4 [isLeaf=0];
5 [isLeaf=1];
6 [isLeaf=0];
7 [isLeaf=1];
8 [isLeaf=0];
9 [isLeaf=1];
1--3  [time=3.41843];
1--4  [time=1.01826];
4--5  [time=4.2496];
2--6  [time=5.59155];
1--6  [time=9.48199];
6--7  [time=7.72868];
0--8  [time=7.38977];
4--8  [time=6.55225];
8--9  [time=0.0406912];
}

我是运行宁的代码:

#include <iostream>
#include <string>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/graph_utility.hpp>

struct Vertex
{
    bool isLeaf;
    std::string taxon;
};


typedef boost::property<boost::edge_weight_t, double> Edge;
typedef boost::adjacency_list<boost::vecS,boost::vecS, boost::undirectedS, Vertex, Edge> Graph;

int main()
{
    Graph g;

    boost::property_map<Graph, boost::edge_weight_t>::type weight = get(boost::edge_weight,g);  

    boost::dynamic_properties dp;
    dp.property("node_id", get(boost::vertex_index, g));
    dp.property("isLeaf", get(&Vertex::isLeaf, g));
    dp.property("time", weight);

    std::string blah = "Hello";

    std::ifstream dot("test.dot");

    boost::read_graphviz(dot,g,dp);

    g[1].taxon = blah;  
}

这个错误的原因是什么?

对 VertexContainerSelector 使用 vecS 意味着您有一个隐式顶点索引描述符。它们是隐含的整数索引顶点描述符¹,恰好是顶点容器的整数索引。

因此,标准 vertex_index 属性 是只读的

Thought Experiment: what would writing to it mean?

If you changed the vertex_index property of a vertex, should it move around, physically, in memory? What if it overwrites an existing Vertex? What about the old location? Should the container be compacted? But that means that assigning a vertex index to a single vertex potentially changes all other vertex indices etc.)

您可以通过多种方式解决这个问题。最简单的方法似乎是向 Vertex 包中添加一个字段,以包含从输入中读取的节点 ID 属性:

#include <iostream>
#include <string>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/graph/graph_utility.hpp>

struct Vertex {
    int id;
    bool isLeaf;
    std::string taxon;
};


typedef boost::property<boost::edge_weight_t, double> Edge;
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, Vertex, Edge> Graph;

int main()
{
    Graph g;
    boost::property_map<Graph, boost::edge_weight_t>::type weight = get(boost::edge_weight,g);  

    boost::dynamic_properties dp;
    dp.property("node_id", get(&Vertex::id, g));
    dp.property("isLeaf", get(&Vertex::isLeaf, g));
    dp.property("time", weight);

    std::string blah = "Hello";

    std::ifstream dot("test.dot");

    boost::read_graphviz(dot,g,dp);

    g[1].taxon = blah;  
}