【问题标题】:copy_graph - adjacency_list with bundled propertiescopy_graph - 具有捆绑属性的 adjacency_list
【发布时间】:2016-02-25 00:45:47
【问题描述】:

这是一个完整的 sn-p 用于复制具有捆绑属性的图形,但会导致一堆编译器错误。需要什么来解决这些问题?

struct NodeInfo1    {};
struct EdgeInfo1 {};

typedef boost::labeled_graph< boost::adjacency_list<
    boost::vecS, boost::vecS, boost::undirectedS, NodeInfo1, EdgeInfo1>,
    std::string> Graph1;

typedef std::pair<boost::graph_traits<Graph>::edge_descriptor, bool> Edge;


void TestCases::TestCopyGraph()
{
    Graph1 grid, g1;
    EdgeInfo1 ei;

    Edge e = add_edge_by_label("A", "B", ei, grid);
    copy_graph(grid, g1);
}

【问题讨论】:

    标签: c++ boost graph properties boost-graph


    【解决方案1】:

    这有点歪曲了这个问题。您实际上不是在复制邻接列表,而是在复制labeled_graph 适配器,这恰好不满足copy_graph 要求的概念:

    /** @name Labeled Mutable Graph
     * The labeled mutable graph hides the add_ and remove_ vertex functions from
     * the mutable graph concept. Note that the remove_vertex is hidden because
     * removing the vertex without its key could leave a dangling reference in
     * the map.
     */
    

    这里复制了 adjacency_list:¹

    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, NodeInfo1, EdgeInfo1> AList;
    typedef boost::labeled_graph<AList, std::string> Graph;
    
    void TestCopyGraph()
    {
        std::string names[3] = { "A", "B", "C" };
        Graph grid(3, names);
        EdgeInfo1 ei;
    
        /*auto e =*/ add_edge_by_label("C", "B", ei, grid);
    
        AList g1;
        copy_graph(grid, g1);
    }
    

    复制带标签的适配器

    更容易。不需要copy_graph,只需复制构造对象即可:

    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/copy.hpp>
    #include <boost/graph/labeled_graph.hpp>
    #include <boost/graph/graph_utility.hpp>
    
    struct NodeInfo1 { int i; };
    struct EdgeInfo1 { int j; };
    
    typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, NodeInfo1, EdgeInfo1> AList;
    typedef boost::labeled_graph<AList, std::string> Graph;
    
    auto TestCopyGraph()
    {
        std::string names[3] = { "A", "B", "C" };
          NodeInfo1 props[3] = { {11}, {22}, {33} };
        Graph grid(3, names, props);
        /*auto e =*/ add_edge_by_label("C", "B", EdgeInfo1{17}, grid);
    
        Graph g1 = grid; // just copy-construct
        return g1;
    }
    
    int main() {
        auto copied = TestCopyGraph();
    
        print_graph(copied);
    
        // check that properties were copied: vertex B has NodeInfo1 22
        {
            auto pmap = boost::get(&NodeInfo1::i, copied);
            std::cout << "Vertex B NodeInfo1.i after copy: " << pmap[copied.vertex("B")] << "\n";
        }
    
        // edge properties too:
        for (auto e : boost::make_iterator_range(edges(copied)))
            std::cout << "Edge has property EdgeInfo1 " << copied[e].j << "\n";
    
        std::cout << "Removed A:\n";
        copied.remove_vertex("A");
        print_graph(copied);
    }
    

    打印

    0 <--> 
    1 <--> 2 
    2 <--> 1 
    Vertex B NodeInfo1.i after copy: 22
    Edge has property EdgeInfo1 17
    Removed A:
    0 <--> 1 
    1 <--> 0 
    

    ¹ 请注意,由于labeled_graph 中的错误,您需要此补丁:https://github.com/boostorg/graph/pull/58

    【讨论】:

    • 谢谢@Sehe。有没有办法去除边缘?一对顶点之间可能有多个边。这就是使用 /*auto e = */ 拥有唯一句柄的原因。但是该句柄在复制的图表上可能不再有效
    • 当然该句柄在复制的图形上无效。找到边缘并将其从那里移除。 paste.ubuntu.com/15202442
    • 谢谢,看起来不错,但是两个顶点之间有多个边,我想专门删除一个而不是其他的
    • 您需要一条识别信息(推荐边缘捆绑中的属性)/或/您需要手动复制保持原始边缘和复制边缘之间的映射(不推荐)。
    猜你喜欢
    • 2011-11-23
    • 2016-01-25
    • 2015-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2015-08-22
    相关资源
    最近更新 更多