【问题标题】:Make a subgraph of a boost graph by removing leaves通过删除叶子制作提升图的子图
【发布时间】:2017-11-01 17:46:46
【问题描述】:

我有一个 vecS 类型的 BGL 图。我想通过移除叶子来制作它的新图表。我需要它主要用于可视化,因为有很多叶子我不需要可视化。根据这个帖子c++ remove vertex from a graphBGL page 从 vecS 邻接列表中删除顶点是不安全的。那么在我的情况下,我有一个 vecS 图的解决方案是什么?我如何制作没有叶子的新图表。

    /// vertex properties
struct VertexData
{
    std::string label;
    int num;
    bool is_leaf=false;
};

/// edges properties
struct EdgeData
{
    std::string edge_name;
    double edge_confidence;
};

/// define the boost-graph
typedef boost::adjacency_list<boost::vecS, boost::vecS,
        boost::bidirectionalS,
        boost::property<boost::vertex_index_t , size_t , VertexData>,
        boost::property<boost::edge_weight_t, double, EdgeData> > Graph;

感谢您的回答。

PS。是否可以使用predicatefiltered_graph

【问题讨论】:

    标签: c++11 boost boost-graph


    【解决方案1】:

    您有一个布尔标志来指示什么是叶子,这有点令人惊讶。在图的性质中,假设叶子是任何出度为 0 的顶点似乎是合乎逻辑的。

    无论如何:

    Live On Coliru

    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/filtered_graph.hpp>
    #include <boost/graph/graph_utility.hpp>
    
    /// vertex properties
    struct VertexData {
        std::string label;
        int num;
        bool is_leaf=false;
    };
    
    /// edges properties
    struct EdgeData {
        std::string edge_name;
        double edge_confidence;
    };
    
    /// define the boost-graph
    typedef boost::adjacency_list<boost::vecS, boost::vecS,
            boost::bidirectionalS,
            boost::property<boost::vertex_index_t, size_t, VertexData>,
            boost::property<boost::edge_weight_t, double, EdgeData> > Graph;
    
    using Predicate = std::function<bool(Graph::vertex_descriptor)>;
    using Filtered  = boost::filtered_graph<Graph, boost::keep_all, Predicate>;
    
    Graph make_graph();
    
    int main() {
        Graph g = make_graph();
        auto const labels = get(&VertexData::label, g);
    
        std::cout << "\n---Main graph:\n";
        print_graph(g, labels);
    
        // manual markings
        {
            auto manual_is_leaf = [&g](Graph::vertex_descriptor vd) { return !g[vd].is_leaf; };
            Filtered manual(g, boost::keep_all{}, manual_is_leaf);
    
            {
    
                std::cout << "\n---Filtered, no leafs:\n";
                print_graph(manual, labels);
            }
    
            {
                std::cout << "\n---Filtered, manual leafs:\n";
                g[2].is_leaf = true; // only "three"
    
                print_graph(manual, labels);
            }
        }
    
        // automatic, dynamic markings
        {
            // note that for bidirectional/undirected out_degree might not make
            // sense, but neither does the notion of a leaf! 
            auto by_degree = [&g](Graph::vertex_descriptor vd) { return boost::out_degree(vd, g); };
            Filtered automatic(g, boost::keep_all{}, by_degree);
    
            {
                std::cout << "\n---Filtered by actual out_degree:\n";
                print_graph(automatic, labels);
            }
    
            {
                // make `five` and `six` appear:
                add_edge(5, 4, 100, g); // six -> five
    
                std::cout << "\n---After adding an edge:\n";
                print_graph(automatic, labels);
            }
        }
    }
    
    Graph make_graph() {
        Graph g;
    
        auto v1 = add_vertex({ 1, {"one",   100, false} }, g);
        auto v2 = add_vertex({ 2, {"two",   200, false} }, g);
        auto v3 = add_vertex({ 3, {"three", 300, false} }, g);
        auto v4 = add_vertex({ 4, {"four",  400, false} }, g);
        auto v5 = add_vertex({ 5, {"five",  500, false} }, g);
        auto v6 = add_vertex({ 6, {"six",   600, false} }, g);
    
        add_edge(v1, v2, 0.5, g);
        add_edge(v2, v3, 0.5, g);
        add_edge(v3, v4, 0.5, g);
        add_edge(v3, v5, 0.5, g);
        add_edge(v3, v6, 0.5, g);
        add_edge(v2, v4, 0.5, g);
        add_edge(v3, v5, 0.5, g);
        add_edge(v4, v6, 0.5, g);
    
        return g;
    }
    

    打印

    ---Main graph:
    one --> two 
    two --> three four 
    three --> four five six five 
    four --> six 
    five --> 
    six --> 
    
    ---Filtered, no leafs:
    one --> two 
    two --> three four 
    three --> four five six five 
    four --> six 
    five --> 
    six --> 
    
    ---Filtered, manual leafs:
    one --> two 
    two --> four 
    four --> six 
    five --> 
    six --> 
    
    ---Filtered by actual out_degree:
    one --> two 
    two --> three four 
    three --> four 
    four --> 
    
    ---After adding an edge:
    one --> two 
    two --> three four 
    three --> four six 
    four --> six 
    six --> 
    

    注意

    如果您想更“真实”地理解双向/无向图的性质,请将 boost::out_degree 替换为 boost::degree(请参阅评论)。在这种情况下,您将在自动部分中看到所有顶点,因为所有顶点都与 some 边相连。

    【讨论】:

    • 感谢您的回答。我使用is_leaf 标志的原因是我有一些未连接的顶点不是叶子,但如果我得到它们的out_degree,那么它将被视为叶子。我决定使用directedS,暂时能够以安全的方式使用自动过滤。无论如何,我使用自动代码修改return boost::out_degree(vd, g) != 0 ,一切都按预期工作。
    • 我有两个 IDE 错误,代码编译和结果是正确的,但我有以下来自 IDE 的错误:1.using Predicate = std::function&lt;bool(Graph::vertex_descriptor)&gt; 错误是can't resolve struct member vertex_descriptor,第二个在这里:2.@ 987654331@ 其中 dp 是 dynamic property 我得到错误:can't resolve variable get 。为什么会出现这些错误,是否可以将新的 filtered_graph 用作原始图的精确过滤实例
    猜你喜欢
    • 1970-01-01
    • 2015-10-09
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-02-01
    • 2015-10-02
    • 1970-01-01
    相关资源
    最近更新 更多