首页 文章

BGL:邻接列表返回描述符的错误边缘属性

提问于
浏览
1

我有一个图表存储为邻接列表 . vertex属性包含一个int ID,而edge属性包含一个4x4矩阵和一个权重;

在测试用例中,图形是一个3顶点图形,边缘连接每对顶点(一个完整的图形) .

我有一个边缘描述符 PathType 的向量,表示一个路径,我正在迭代它并访问每个边缘及其属性 RelationshipEdge ,如下所示 .

for(PathType::iterator pathIterator = path.begin(); pathIterator != path.end(); ++pathIterator){
        edge_t edge = *pathIterator;
        RelationshipEdge rEdge = m_graph[edge];
        int sourceID = m_graph[boost::source(edge, m_graph)].id;
        int destID = m_graph[boost::target(edge, m_graph)].id;

但是,有时执行此操作时, RelationshipEdge 返回包含错误边缘的数据 .

例如,检查 edge 显示 m_source 为1和 m_target 为2.如果我检查图形并找到具有源1和目标2的边缘,则权重为3且矩阵为输入 . 然而,rEdge的权重为1,并且矩阵不同 . 这些值实际上与源0和目标1的边对应 .

我是否正确访问了边缘属性?

我的图表类型的定义是:

typedef boost::adjacency_list< 
boost::vecS, boost::vecS, boost::undirectedS, MarkerVertex, RelationshipEdge>
CorrelationAdjacencyList;

3 回答

  • 0

    我相信你的错误来自代码库中的其他地方 .

    我把这个简单的代码放在一起测试边缘访问和类似图表上的顺序,一切都按预期工作 .

    如上所述,罪犯可以手动维护 edge_descriptorsvertex_descriptors . 或者也许你的路径矢量初始化或构造 .

    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/graph_traits.hpp>
    
    using namespace std;
    
    enum edge_t {A,B};
    
    struct MarkerVertex{
        std::string id;
    };
    
    struct RelationshipEdge{
        std::string id;
    };
    
    
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS,
        MarkerVertex, RelationshipEdge> CorrelationAdjacencyList;
    
    
    typedef boost::graph_traits<CorrelationAdjacencyList>::edge_descriptor   Edge;
    typedef boost::graph_traits<CorrelationAdjacencyList>::vertex_descriptor Vertex;
    
    typedef vector<Edge> PathType;
    
    
    void printPath(PathType &p, CorrelationAdjacencyList &g){
        cout << "print path" << endl;
    
        for(PathType::iterator pi = p.begin(); pi != p.end(); ++pi){
            Edge e = *pi;
    
            Vertex s = boost::source(e,g);
            Vertex t = boost::target(e,g);
    
            cout << g[s].id << "\t" 
                 << g[e].id << "\t"
                 << g[t].id << endl;
    
            bool isFound;
            Edge eForward;
            boost::tie(eForward,isFound) = boost::edge(s,t,g);
            cout << "forward  " << g[eForward].id << "\t" << isFound << endl;
    
            Edge eBackward;
            boost::tie(eBackward,isFound) = boost::edge(t,s,g);
            cout << "backward " << g[eBackward].id << "\t" << isFound << endl;
        }
    }
    
    
    int main(int argc, char* argv[]){
    
        CorrelationAdjacencyList graph;
    
        Vertex a = boost::add_vertex(graph); graph[a].id = "a";
        Vertex b = boost::add_vertex(graph); graph[b].id = "b";
        Vertex c = boost::add_vertex(graph); graph[c].id = "c";
    
        Edge e1 = boost::add_edge(a,b,graph).first; graph[e1].id = "e1";
        Edge e2 = boost::add_edge(b,c,graph).first; graph[e2].id = "e2";
        Edge e3 = boost::add_edge(c,a,graph).first; graph[e3].id = "e3";
    
        PathType path1,path2,path3;
    
        path1.push_back(e1);
        path1.push_back(e2);
        path1.push_back(e3);
    
        path2.push_back(e2);
        path2.push_back(e3);
        path2.push_back(e1);
    
        path3.push_back(e3);
        path3.push_back(e2);
        path3.push_back(e1);
    
        printPath(path1,graph);
        cout << endl;
        printPath(path2,graph);
        cout << endl;
        printPath(path3,graph);
    
    
        cin.get();
    }
    
  • 2

    没有进一步的信息,我可以做出有根据的猜测,你使用 vecS 容器,迭代器/引用已经失效 .

    在插入/删除边/顶点时会发生这种情况 .

  • 0

    这是我找到的解决方案,虽然我不相信我完全理解为什么原始方法没有 .

    我用上面的代码替换了

    for(PathType::iterator pathIterator = path.begin(); pathIterator != path.end(); ++pathIterator){
        edge_t edge = *pathIterator;
    
        int sourceID = m_graph[boost::source(edge, m_graph)].id;
        int destID = m_graph[boost::target(edge, m_graph)].id;
    
        int lowerID, higherID;
        if (sourceID < destID){
            lowerID = sourceID;
            higherID = destID;
        } else {
            lowerID = destID;
            higherID = sourceID;
        }
    
        edge_t edge2 = m_edgeDescriptorsByEndpoints.at(make_pair(lowerID, higherID));
        RelationshipEdge rEdge = m_graph[edge2];
    

    m_edgeDescriptorsByEndpoints 是边对描述符的顶点ID对的映射 .

    所以我正在获取边缘描述符,获取源顶点和目标顶点的ID,从 Map 中找到相应的边缘描述符,然后获取该边缘的属性 .

    不完全是一个令人满意的解决方案,但它确实有效,因为到目前为止我已经能够测试 .

    EDIT

    我按照@sehe的建议调用 boost::edge(u,v,g) 将调用替换为我的 Map ,所以代码现在如下:

    for(PathType::iterator pathIterator = path.begin(); pathIterator != path.end(); ++pathIterator){
                edge_t edge = *pathIterator;
    
                vert_t sourceV = boost::source(edge, m_graph);
                vert_t targetV = boost::target(edge, m_graph);
    
                pair<edge_t, bool> edgePair = boost::edge(sourceV, targetV, m_graph);
                if (!edgePair.second){
                    cerr << "Edge does not exist" << endl;
                }
                RelationshipEdge rEdge = m_graph[edgePair.first];
    

    这段代码仍会导致rEdge包含正确的属性,这看起来很奇怪,因为我认为查询边缘顶点的图形,然后查询图形中连接这些顶点的边缘总会给你完全相同的边后卫 .

相关问题