【问题标题】:Attach an external property map to a graph将外部属性映射附加到图形
【发布时间】:2017-01-10 22:48:19
【问题描述】:

将边权重作为内部属性添加到图是很简单的:

void InternalProperties()
{
    std::cout << "InternalProperties()" << std::endl;

    // Graph with internal edge weights
    using EdgeWeightProperty = boost::property<boost::edge_weight_t, double>; // <tag, type>

    using GraphWithInternalEdgeWeightsType =  boost::adjacency_list<boost::setS, // out edge container
                                                                    boost::vecS, // vertex container
                                                                    boost::undirectedS, // directed or undirected
                                                                    boost::no_property, // vertex properites
                                                                    EdgeWeightProperty> // edge properties
                                                                    ;

    // Create a graph object
    GraphWithInternalEdgeWeightsType g(3);

    // add two edges with edge weights
    EdgeWeightProperty e1 = 5;
    add_edge(0, 1, e1, g);

    EdgeWeightProperty e2 = 3;
    add_edge(1, 2, e2, g);

    boost::property_map<GraphWithInternalEdgeWeightsType, boost::edge_weight_t>::type edgeWeightMap = get(boost::edge_weight_t(), g);

    using edge_iter = boost::graph_traits<GraphWithInternalEdgeWeightsType>::edge_iterator;
    std::pair<edge_iter, edge_iter> edgePair;
    for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first) {
      std::cout << edgeWeightMap[*edgePair.first] << " ";
    }
}

现在,如果我想做同样的事情并演示使用“外部属性”,我想出了这个,但实际上根本没有回到原始图表的链接:

void ExternalProperties()
{
    std::cout << std::endl << "ExternalProperties()" << std::endl;

    // Graph with external edge weights
    using GraphWithExternalEdgeWeightsType =  boost::adjacency_list<boost::setS, // out edge container
                                                                    boost::vecS, // vertex container
                                                                    boost::undirectedS> // directed or undirected
                                                                    ;

    // Create a graph object
    GraphWithExternalEdgeWeightsType g(3);

    // add edges (without edge weights)
    add_edge(0, 1, g);
    add_edge(1, 2, g);

    // create a map from edge_descriptors to weights and populate it
    std::map<GraphWithExternalEdgeWeightsType::edge_descriptor, double> edgeWeightMap;
    edgeWeightMap[boost::edge(0,1,g).first] = 5;
    edgeWeightMap[boost::edge(1,2,g).first] = 3;

    using edge_iter = boost::graph_traits<GraphWithExternalEdgeWeightsType>::edge_iterator;
    std::pair<edge_iter, edge_iter> edgePair;
    for(edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first) {
      std::cout << edgeWeightMap[*edgePair.first] << " ";
    }
}

有没有办法让get(boost::edge_weight_t(), g);(来自内部示例)返回这张地图?喜欢在这个外部示例中说g.setPropertyMap(boost::edge_weight_t, edgeWeightMap)

【问题讨论】:

    标签: c++ boost boost-graph


    【解决方案1】:

    我不确定有什么收获,但也许这有助于激发灵感:

    #include <boost/graph/adjacency_list.hpp>
    #include <boost/property_map/property_map.hpp>
    #include <map>
    #include <iostream>
    
    namespace MyLib {
        struct MyGraph : boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS> {
            using base_type = boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS>;
            using base_type::adjacency_list;
    
            std::map<edge_descriptor, double> m_weights;
        };
    
        auto get(boost::edge_weight_t, MyGraph& g)       { return boost::make_assoc_property_map(g.m_weights); }
        auto get(boost::edge_weight_t, MyGraph const& g) { return boost::make_assoc_property_map(g.m_weights); }
    }
    
    namespace boost {
        template <> struct graph_traits<MyLib::MyGraph> : graph_traits<adjacency_list<setS, vecS, undirectedS> > {};
    
        template <> struct property_map<MyLib::MyGraph, edge_weight_t, void> {
            using Traits = graph_traits<MyLib::MyGraph>;
    
            using Edge       = Traits::edge_descriptor;
            using type       = boost::associative_property_map<std::map<Edge, double> >;
            using const_type = boost::associative_property_map<std::map<Edge, double> > const;
        };
    }
    
    void ExternalProperties() {
        std::cout << "ExternalProperties()" << std::endl;
    
        // Graph with external edge weights
        // Create a graph object
        using Graph = MyLib::MyGraph;
        Graph g(3);
    
        // add edges (without edge weights)
        add_edge(0, 1, g);
        add_edge(1, 2, g);
    
        // create a map from edge_descriptors to weights and populate it
        auto edgeWeightMap = MyLib::get(boost::edge_weight, g);
        edgeWeightMap[boost::edge(0, 1, g).first] = 5;
        edgeWeightMap[boost::edge(1, 2, g).first] = 3;
    
        using edge_iter = boost::graph_traits<Graph>::edge_iterator;
        std::pair<edge_iter, edge_iter> edgePair;
    
        for (edgePair = edges(g); edgePair.first != edgePair.second; ++edgePair.first) {
            std::cout << edgeWeightMap[*edgePair.first] << " ";
        }
    }
    
    int main() {
        ExternalProperties();
    }
    

    我无法避免与 boost::get 的歧义,这样您就可以信任 ADL 来选择没有命名空间限定的“最佳”重载。

    Live On Coliur

    【讨论】:

    • 所以这有点像制作你自己的类似图形的容器,其行为就像我要求的那样,而不是让实际的 adjacency_list 表现得像那样。所以我猜你是在确认实际上没有办法让实际的boost::edge_weight_t 上的adjacency_list 相信它是外部属性映射。那么这个概念是任何 BGL 算法都应该接受像 std::map 这样的东西来处理它直接需要的任何字段,并且不需要按照我的要求做?
    • 你认为这如何工作?您可以使用图形属性来存储状态,但不能在类型中编码运行时状态。这是物理定律。
    • 想象一下发生了标签调度之类的事情,Boost 图形类中返回 edge_weight_t 的边权重的函数只需要一个包含我的边权重容器的函子,然后它就可以把它返还。我离这里很远吗?
    猜你喜欢
    • 2018-06-17
    • 1970-01-01
    • 1970-01-01
    • 2011-09-25
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多