BGL:邻接列表返回描述符

时间:2015-05-19 10:52:03

标签: c++ graph boost-graph adjacency-list

我有一个图表存储为邻接列表。 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 :(得分:2)

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

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

如上所述,可以手动维护罪犯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();
}

答案 1 :(得分:0)

如果没有进一步的信息,我可以做出有根据的猜测,即使用vecS个容器并且迭代器/引用已经失效。

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

答案 2 :(得分:0)

以下是我找到的解决方案,但我并不相信我完全理解为什么原始方法没有。

我用

替换了上面的代码
map.on('zoomend', function() {
    var currentZoom = map.getZoom();
    overlayGroup.clearLayers() //remove existing
    overlayGroup.addLayer(myZoomLevelMapping[currentZoom]) //add layer for this zoom level.
})

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]; 是一对顶点ID到边描述符的映射。

所以我采用边缘描述符,获取源顶点和目标顶点的ID,从地图中找到相应的边缘描述符,然后获取该边缘的属性。

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

修改

我按照@sehe的建议调用m_edgeDescriptorsByEndpoints来调用我的地图,所以代码如下:

boost::edge(u,v,g)

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