简体   繁体   English

具有自定义顶点属性的图形的增强支配树

[英]Boost dominator tree for graph with custom vertex properties

I'm trying to use boost::lengauer_tarjan_dominator_tree with a graph with custom vertex properties , but can't get even a simple example to compile:我正在尝试将boost::lengauer_tarjan_dominator_tree与具有自定义顶点属性的图形一起使用,但甚至无法获得一个简单的编译示例:

#include <vector>
#include <iterator>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dominator_tree.hpp>
#include <boost/property_map/property_map.hpp> 

struct GraphNode
{
    explicit GraphNode(unsigned i) : index {i} {}
    unsigned index;
};

using Graph = boost::adjacency_list<boost::listS, boost::listS, 
                            boost::bidirectionalS, GraphNode, boost::no_property>;

using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

int main()
{
    Graph g {};

    const auto u = boost::add_vertex(GraphNode {0}, g);
    const auto v = boost::add_vertex(GraphNode {1}, g);
    const auto x = boost::add_vertex(GraphNode {2}, g);
    const auto y = boost::add_vertex(GraphNode {3}, g);
    const auto z = boost::add_vertex(GraphNode {4}, g);

    boost::add_edge(u, v, g);
    boost::add_edge(u, x, g);
    boost::add_edge(v, y, g);
    boost::add_edge(x, y, g);
    boost::add_edge(y, z, g);

    const auto index_map = boost::get(&GraphNode::index, g);

    std::vector<Vertex> dom_tree_pred_vector(boost::num_vertices(g),
                                             boost::graph_traits<Graph>::null_vertex());

    auto dom_tree_pred_map = boost::make_iterator_property_map(std::begin(dom_tree_pred_vector),
                                index_map);

    boost::lengauer_tarjan_dominator_tree(g, u, dom_tree_pred_map);
}

Which I tried to adapt from the example given in the docs.我试图从文档中给出的示例中改编。

Here is part of the error message:这是错误消息的一部分:

/usr/local/include/boost/graph/detail/adjacency_list.hpp:2544:33: error: cannot form a reference to 'void'
        typedef const value_type& const_reference;
                                ^
/usr/local/include/boost/graph/dominator_tree.hpp:355:31: error: no matching function for call to 'get'
    const IndexMap indexMap = get(vertex_index, g);

I've also tried to pass in the index map explicitly using the second form of the method, without success.我还尝试使用该方法的第二种形式显式传入索引映射,但没有成功。 I've noticed this methods interface seems a little different from other graph methods, such as depth_first_search , where the vertex_index_map is a named parameter.我注意到这个方法接口似乎与其他图形方法有点不同,例如depth_first_search ,其中vertex_index_map是一个命名参数。

Is it possible to use this method with custom vertex properties?是否可以将此方法与自定义顶点属性一起使用?

The problem - as ever - is with using something other than vecS for the vertex container.问题 - 一如既往 - 使用vecS以外的东西作为顶点容器。 You lose the builtin vertex_index property, making it mandatory to supply it to the API.您丢失了内置的vertex_index属性,因此必须将其提供给 API。

Sadly this algorithm doesn't support custom vertex index maps well.遗憾的是,该算法不能很好地支持自定义顶点索引图。 You tried - correctly - by using index_map , but internally the algorithm still looks for vertex_index_t tagged property.您尝试 - 正确 - 通过使用index_map ,但在内部算法仍然寻找vertex_index_t标记的属性。

The only two ways in which I can see this work is,我能看到这项工作的唯一两种方式是,

  1. to do the DFS stage manually (as even the all-argument overload of lengauer_tarjan* fails to forward the correct index map into the DFS).手动执行 DFS 阶段(因为即使lengauer_tarjan*的全参数重载也无法将正确的索引映射转发到 DFS)。 Then you could call the lengauer_tarjan_dominator_tree_without_dfs implementation and have the result.然后你可以调用lengauer_tarjan_dominator_tree_without_dfs实现并获得结果。

  2. Alternatively you could tell the library about your graph's index map.或者,您可以将图形的索引图告诉图书馆。

(Lastly, you could accept fate and use vecS as the vertex container selector. I suspect this is explicitly not what you wanted.) (最后,你可以接受命运并使用vecS作为顶点容器选择器。我怀疑这显然不是你想要的。)

DEMO演示

Using the second approach, which may be the most elegant.使用第二种方法,这可能是最优雅的。 Here are the specializations/overloads to add:以下是要添加的专业化/重载:

namespace boost {
    template <>
        struct property_map<Graph, vertex_index_t> {
            typedef typename property_map<Graph, size_t GraphNode::*>::type type;
            typedef typename property_map<Graph, size_t GraphNode::*>::const_type const_type;
        };

    static auto get(vertex_index_t, Graph& g)       { return get(&GraphNode::index, g); }
    static auto get(vertex_index_t, Graph const& g) { return get(&GraphNode::index, g); }
}

Live On Coliru 住在 Coliru

#include <vector>
#include <iterator>
#include <iostream>

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dominator_tree.hpp>
#include <boost/property_map/property_map.hpp> 

struct GraphNode
{
    explicit GraphNode(size_t i) : index {i} {}
    size_t index;
};

using Graph = boost::adjacency_list<boost::listS, boost::listS, boost::bidirectionalS, GraphNode, boost::no_property>;

namespace boost {
    template <>
        struct property_map<Graph, vertex_index_t> {
            typedef typename property_map<Graph, size_t GraphNode::*>::type type;
            typedef typename property_map<Graph, size_t GraphNode::*>::const_type const_type;
        };

    static property_map<Graph, vertex_index_t>::type       get(vertex_index_t, Graph& g)       { return get(&GraphNode::index, g); }
    static property_map<Graph, vertex_index_t>::const_type get(vertex_index_t, Graph const& g) { return get(&GraphNode::index, g); }
}

using Vertex = boost::graph_traits<Graph>::vertex_descriptor;

int main()
{
    Graph g {};

    const auto u = boost::add_vertex(GraphNode {0}, g);
    const auto v = boost::add_vertex(GraphNode {1}, g);
    const auto x = boost::add_vertex(GraphNode {2}, g);
    const auto y = boost::add_vertex(GraphNode {3}, g);
    const auto z = boost::add_vertex(GraphNode {4}, g);

    boost::add_edge(u, v, g);
    boost::add_edge(u, x, g);
    boost::add_edge(v, y, g);
    boost::add_edge(x, y, g);
    boost::add_edge(y, z, g);

    std::vector<Vertex> dom_pred(num_vertices(g), boost::graph_traits<Graph>::null_vertex());

    auto index_map = boost::get(&GraphNode::index, g); // equivalent to vertex_index_t now
    auto dom_tree_pred_map (boost::make_iterator_property_map(std::begin(dom_pred), index_map));

    // Run main algorithm
    boost::lengauer_tarjan_dominator_tree(g, u, dom_tree_pred_map);

    std::cout << "Result: ";
    for (auto v : dom_pred) {
        if (v == boost::graph_traits<Graph>::null_vertex())
            std::cout << "(root) "; 
        else
            std::cout << g[v].index << " "; 
    }
}

Prints印刷

Result: (root) 0 0 0 3 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM