簡體   English   中英

BGL:鄰接表返回錯誤的描述符邊緣屬性

[英]BGL: adjacency list returns wrong edge property for descriptor

我有一個圖存儲為鄰接表。 頂點屬性保存一個int ID,邊緣屬性保存一個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;

我相信您的錯誤來自代碼庫中的其他地方。

我將這些簡單的代碼組合在一起,以在相似的圖形上測試邊緣訪問和順序,並且一切正常。

如上文所述,罪犯可以手動維護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();
}

如果沒有更多信息,我可以根據您的猜測使用vecS容器,並且迭代器/引用已失效。

這將在邊/頂點的插入/刪除時發生。

這是我找到的解決方案,盡管我不確定我是否完全理解原始方法為何沒有。

我已將上面的代碼替換為

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,從地圖中找到相應的邊緣描述符,然后獲取該邊緣的屬性。

就我到目前為止所能測試的而言,這不是一個令人滿意的解決方案,但它確實有效。

編輯

我用@sehe建議的對boost::edge(u,v,g)的調用代替了對地圖的調用,因此代碼如下:

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包含正確的屬性,這似乎很奇怪,因為我認為查詢圖形中的邊的頂點,然后查詢圖形中的連接這些頂點的邊,總是會得到相同的結果邊緣向后。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM