提升图形复制和删除顶点

时间:2015-07-20 17:29:41

标签: c++ boost graph

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

我有一个提升图g1,我从中提取了几个顶点描述符。现在我想使用这个顶点描述符对名为g1的{​​{1}}副本进行一些处理。如果我使用以下内容:

g2

复制图形然后我可以使用g2 = g1; 中使用g2提取的顶点描述符来访问g1的顶点属性,但我无法从图中删除顶点。

g2[vertex_descriptor]

我的图表没有任何内容,顶点仍然存在。

我知道有一个boost::clear_vertex(v, _graph); boost::remove_vertex(v, _graph); 函数可用,但我并不理解(或者我不知道如何阅读)doc而且copy_graph会产生很多错误:

boost::copy_graph(g1, g2)

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

1 个答案:

答案 0 :(得分:7)

天真的方法出了什么问题?

正如我对另一个答案所评论的那样,只需通过源顶点描述符删除顶点就可以正常工作,因为它会使变异副本中的所有较高顶点无效。

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

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

对于紧要关头,如果顶点描述符不是一个完整的类型,那么根本不会起作用,例如当顶点容器选择器不是boost::vecS(listS,setS等)时。

如何解决?

BGL有两个原语似乎适用于此:

  1. Filtered Graphs;

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

  2. Subgraphs

    如果您希望(嵌套)父图和子图之间存在双向可变关系,这是最合适的。即如果您在构建图形时知道 图形“层次结构”的“级别”中的哪些节点,则可以使用boost::subgraph<>层次结构表示。这些将自动保持同步;即,如果将节点添加到子图中,父图也将包含它;如果修改/删除子图中的边,则所有父图中反映的“实时”变化相同。

  3. 在这种情况下,我认为filtered_graph<>非常接近您的需求。这是一个编写图表的演示,并使用std::set<vertex_descriptor>对其进行“实时过滤”。使用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);
    }
    

    enter image description here