【问题标题】:Weight map as function in Boost Graph Dijkstra algorithm权重图作为 Boost Graph Dijkstra 算法中的函数
【发布时间】:2016-01-11 06:17:49
【问题描述】:

我正在使用 Boost Graph Libraries 并且需要使用一个权重图,该权重图不是常数,而是参数 K 的函数(即边缘成本取决于 K)。在实践中,给定以下代码:

#include <boost/config.hpp>
#include <iostream>
#include <fstream>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/adjacency_list.hpp>

struct Edge {
        Edge(float weight_) : weight(weight_) {}
        float weight;
        float getWeight(int K)
        {
            return K*weight;
        }
};



int main(int, char**){
        typedef boost::adjacency_list < boost::vecS, boost::vecS, boost::directedS, boost::no_property, Edge > graph_t;
        typedef boost::graph_traits < graph_t >::vertex_descriptor vertex_t;
        graph_t g;
        vertex_t a = boost::add_vertex(g);
        vertex_t b = boost::add_vertex(g);
        vertex_t c = boost::add_vertex(g);
        vertex_t d = boost::add_vertex(g);
        boost::add_edge(a, b, Edge(3), g);
        boost::add_edge(b, c, Edge(3), g);
        boost::add_edge(a, d, Edge(1), g);
        boost::add_edge(d, c, Edge(4), g);

        std::vector<vertex_t> preds(4);

        // Traditional dijsktra (sum)
        boost::dijkstra_shortest_paths(g, a, boost::predecessor_map(&preds[0]).weight_map(boost::get(&Edge::weight,g)));

        return 0;
}

我想调用 Dijkstra 算法如下:

boost::dijkstra_shortest_paths(g, a, boost::predecessor_map(&preds[0]).weight_map(boost::get(&Edge::getWeight(2),g)));

但错误如下

不能调用成员函数'float Edge::getWeight(int)' 对象

有人知道怎么解决吗?

【问题讨论】:

    标签: c++ boost dijkstra boost-graph boost-property-map


    【解决方案1】:

    有许多属性地图风格。特别是transform_value_property_map可以在这里使用。

    简单方法 C++03

    假设你会写 c++03:

    Live On Coliru

    #include <boost/property_map/transform_value_property_map.hpp>
    #include <boost/bind.hpp>
    
    // ...
    
    boost::dijkstra_shortest_paths(g, a, boost::predecessor_map(&preds[0]).weight_map(
                boost::make_transform_value_property_map(
                    boost::bind(&Edge::getWeight ,_1, 2), 
                    boost::get(boost::edge_bundle, g))
            ));
    

    更清洁的 C++11

    Live On Coliru

    auto wmap = make_transform_value_property_map([](Edge& e) { return e.getWeight(2); }, get(boost::edge_bundle, g));
    boost::dijkstra_shortest_paths(g, a, boost::predecessor_map(&preds[0]).weight_map(wmap));
    

    您可以删除 boost/bind.hpp 包含。

    奖励:删除 getWeight() 成员函数

    Live On Coliru

    您实际上并不需要它。您可以就地编写凤凰演员:

    #include <boost/phoenix.hpp>
    using boost::phoenix::arg_names::arg1;
    
    auto wmap = make_transform_value_property_map(2 * (&arg1->*&Edge::weight), get(boost::edge_bundle, g));
    

    或者再次使用c++11:

    Live On Coliru

    auto wmap = make_transform_value_property_map([](Edge& e) { return e.weight * 2; }, get(boost::edge_bundle, g));
    

    【讨论】:

    • 在 Coliru 上添加不少于 4 个活样本 :)
    • 非常感谢!还有一个问题:因为我没有使用 C++11,并且想为三/四个 K 值并行调用 Dijkstra 算法(openMPI?),这对你来说是最快的代码实现吗?
    • 无论 K 是多少,最短路径都应该保持不变。假设图表是逻辑和按位 const,您可以并行运行查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-28
    • 2011-10-11
    • 1970-01-01
    相关资源
    最近更新 更多