【问题标题】:boost graph copy and removing vertex提升图复制和删除顶点
【发布时间】:2015-10-09 22:39:01
【问题描述】:

如何将 boost 图复制到第二个 boost 图中,以便我可以使用从第一个图中提取的顶点描述符来修改第二个而不修改第一个?

我有一个提升图g1,我从中提取了几个顶点描述符。现在我想使用这个顶点描述符对名为g2g1 的副本进行一些处理。如果我使用类似的东西:

g2 = g1;

要复制图形,然后我可以使用从 g1 提取的顶点描述符访问 g2 的顶点属性,使用类似 g2[vertex_descriptor] 的东西,但我无法从图形中删除顶点。

boost::clear_vertex(v, _graph);
boost::remove_vertex(v, _graph);

对我的图形没有任何作用,顶点仍然存在。

我知道有一个可用的 copy_graph 函数,但我不太了解(或者我不知道如何阅读)doc 并且执行 boost::copy_graph(g1, g2) 会产生很多错误:

In file included from /usr/include/boost/graph/adjacency_list.hpp:246:0,
                 from /home/malcolm/AASS/sketch_maker/includes/TopologicalMap/Global.hpp:6,
                 from /home/malcolm/AASS/sketch_maker/includes/MapComparator/Match.hpp:4,
                 from /home/malcolm/AASS/sketch_maker/includes/MapComparator/Hypothese.hpp:4,
                 from /home/malcolm/AASS/sketch_maker/includes/MapComparator/Cluster.hpp:4,
                 from /home/malcolm/AASS/sketch_maker/Test/test_comparisor.cpp:11:
/usr/include/boost/graph/detail/adjacency_list.hpp: In instantiation of ‘struct boost::adj_list_any_vertex_pa::bind_<boost::vertex_index_t, boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, topologicalmap::Place>’:
/usr/include/boost/graph/detail/adjacency_list.hpp:2568:12:   required from ‘struct boost::detail::adj_list_choose_vertex_pa<boost::vertex_index_t, boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, topologicalmap::Place>’
/usr/include/boost/graph/detail/adjacency_list.hpp:2705:12:   required from ‘struct boost::adj_list_vertex_property_selector::bind_<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, topologicalmap::Place, boost::vertex_index_t>’
/usr/include/boost/graph/properties.hpp:217:12:   required from ‘struct boost::detail::vertex_property_map<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, boost::vertex_index_t>’
/usr/include/boost/graph/properties.hpp:228:10:   required from ‘struct boost::property_map<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, boost::vertex_index_t, void>’
/usr/include/boost/graph/detail/adjacency_list.hpp:1688:5:   required by substitution of ‘template<class Config, class Base, class Property> typename boost::property_map<typename Config::graph_type, Property>::const_type boost::get(Property, const boost::adj_list_helper<Config, Base>&) [with Config = boost::detail::adj_list_gen<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property, boost::listS>::config; Base = boost::undirected_graph_helper<boost::detail::adj_list_gen<boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>, boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property, boost::listS>::config>; Property = boost::vertex_index_t]’
/usr/include/boost/graph/copy.hpp:353:57:   required from ‘void boost::copy_graph(const VertexListGraph&, MutableGraph&) [with VertexListGraph = boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>; MutableGraph = boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>]’
/home/malcolm/AASS/sketch_maker/includes/MapComparator/Cluster.hpp:32:150:   required from here
/usr/include/boost/graph/detail/adjacency_list.hpp:2498:29: error: forming reference to void
         typedef value_type& reference;
                             ^
/usr/include/boost/graph/detail/adjacency_list.hpp:2499:35: error: forming reference to void
         typedef const value_type& const_reference;
                                   ^
/usr/include/boost/graph/detail/adjacency_list.hpp:2502:47: error: forming reference to void
           <Graph, value_type, reference, Tag> type;
                                               ^
/usr/include/boost/graph/detail/adjacency_list.hpp:2504:53: error: forming reference to void
           <Graph, value_type, const_reference, Tag> const_type;
                                                     ^
In file included from /home/malcolm/AASS/sketch_maker/includes/TopologicalMap/GraphPlace.hpp:13:0,
                 from /home/malcolm/AASS/sketch_maker/includes/MapComparator/Cluster.hpp:5,
                 from /home/malcolm/AASS/sketch_maker/Test/test_comparisor.cpp:11:
/usr/include/boost/graph/copy.hpp: In instantiation of ‘void boost::copy_graph(const VertexListGraph&, MutableGraph&) [with VertexListGraph = boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>; MutableGraph = boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>]’:
/home/malcolm/AASS/sketch_maker/includes/MapComparator/Cluster.hpp:32:150:   required from here
/usr/include/boost/graph/copy.hpp:353:57: error: no matching function for call to ‘get(boost::vertex_index_t, const boost::adjacency_list<boost::listS, boost::listS, boost::undirectedS, topologicalmap::Place, topologicalmap::Gateway_struct, boost::no_property>&)’
                                   get(vertex_index, g_in), orig2copy[0]),

错误信息比那个大,但我只取了开头。

【问题讨论】:

    标签: c++ boost graph


    【解决方案1】:

    天真的方法有什么问题?

    正如我对另一个答案的评论,简单地通过源顶点描述符删除一个顶点将不会按预期工作,因为它会使变异副本中所有更高的顶点无效。

    因此,如果您要删除第二个顶点,您可能会删除 与预期不同的顶点。

    更糟糕的是,所有属性查找都将无效(如果针对原始属性映射进行)。

    而且对于关键来说,如果顶点描述符一开始不是整数类型,这些都不会起作用,例如当顶点容器选择器不是boost::vecS(listS、setS 等)时。

    如何解决?

    BGL 有两个在这里似乎适用的原语:

    1. Filtered Graphs;

      这里您不创建实际副本,只需通过提供(可选)顶点和边过滤谓词来创建原始图的“过滤视图”。

    2. Subgraphs

      如果您想要(嵌套)父图和子图之间的双向可变关系,这是最合适的。 IE。如果您在构建图表时知道哪些节点位于图表“层次结构”的哪个“级别”中,则可以使用boost::subgraph&lt;&gt; 层次结构来表达。这些将自动保持同步;即,如果您将节点添加到子图,则父图也将包含它;如果您修改/删除子图中的边,则相同的更改会“实时”反映在所有父图中。

    在这种情况下,我认为filtered_graph&lt;&gt; 非常接近您的需求。这是一个编写图表的演示,并使用std::set&lt;vertex_descriptor&gt;“实时过滤”它。结果使用 GraphViz 可视化:

    Live On Coliru

    #include <boost/graph/adjacency_list.hpp>
    #include <iostream>
    
    using namespace boost;
    
    struct VertexProperties {
        int id;
        std::string label;
    };
    
    struct EdgeProperties {
        double weight;
    };
    
    using Graph_t = boost::adjacency_list<listS, listS, directedS, VertexProperties, EdgeProperties>;
    
    //////////////////////////////////////////////////
    // saving dotfiles for rendering to PNG
    #include <boost/graph/graphviz.hpp>
    
    template <typename G>
    void save_dot_file(std::string const& fname, G& graph) {
        dynamic_properties dp;
        dp.property("node_id", boost::get(&VertexProperties::id,    graph));
        dp.property("label",   boost::get(&VertexProperties::label, graph));
        dp.property("weight",  boost::get(&EdgeProperties::weight,  graph));
    
        std::ofstream ofs(fname);
        write_graphviz_dp(ofs, graph, dp);
    }
    
    //////////////////////////////////////////////////
    // Filtering graphs with a simple vertex filter
    #include <boost/graph/filtered_graph.hpp>
    #include <boost/function.hpp>
    
    using V        = Graph_t::vertex_descriptor;
    using Filtered = filtered_graph<Graph_t, keep_all, boost::function<bool(V)> >;
    
    //////////////////////////////////////////////////
    // Demo
    int main()
    {
        Graph_t g;
    
        // have a filtered "copy" f that just removes a set of vertices:
        std::set<V> removed_set;
        Filtered f(g, keep_all{}, [&](V v){ return removed_set.end() == removed_set.find(v); });
    
        // build a demo graph with 3 vertices
        auto u = boost::add_vertex(VertexProperties{ 10, "Ten"    }, g);
        auto v = boost::add_vertex(VertexProperties{ 20, "Twenty" }, g);
        auto w = boost::add_vertex(VertexProperties{ 30, "Thirty" }, g);
    
        /*auto e1 =*/ boost::add_edge(u, v, EdgeProperties { 0.5 }, g);
        /*auto e2 =*/ boost::add_edge(v, w, EdgeProperties { 1.5 }, g);
        /*auto e3 =*/ boost::add_edge(w, u, EdgeProperties { 2.5 }, g);
    
        ///////////////////////////////////////
        // save the original graph
        save_dot_file("original.dot", g);
    
        // empty filter:
        save_dot_file("filtered1.dot", f);
    
        // removing `v` ("Twenty")
        removed_set.insert(v);
        save_dot_file("filtered2.dot", f);
    }
    

    【讨论】:

    • @Daniel-san :) 由于您对 BGL 感兴趣并且那里有一个工作示例,您可能想了解演示中的 filtered_graph。只是为了让你觉得这并不容易:你可以在这里看到我挣扎的实时编码流:part #1part #2part #3
    • 看你的解释,过滤的图表更适合我的使用。我的新问题是我还需要能够将边添加到我的第二个图形(不修改第一个图形),并且从我读到的图形过滤不允许这样做。但这不是我的问题,它解决了顶点问题。对于边缘,我觉得我可以简单地添加一些边缘,将描述符保存在某处,然后在处理结束时将它们从图中抑制。非常感谢。
    • 你可以让两个图都从一个超图过滤。但是到这个时候,您应该首先将所有需求/使用模式绘制成图表。它已经开始转向subgraph&lt;&gt;
    • 我认为这实际上是最好的方法。但这意味着现在要进行大量重写。我会记住的。
    • 我只是想评论一下filtered_graphs的一个API“限制”。 num_vertices(filtered_graph)num_edges(filtered_graph) 将返回原始图的节点数和边数。您需要使用 boost::vertices(filtered_graph)boost::nodes(filtered_graph) 并计算它们以获得正确的值。
    猜你喜欢
    • 1970-01-01
    • 2018-02-01
    • 1970-01-01
    • 2011-11-04
    • 1970-01-01
    • 2021-09-03
    • 1970-01-01
    • 2015-07-19
    • 2011-03-07
    相关资源
    最近更新 更多