在Boost Graph Dijkstra算法中,权重映射是一个函数。

4

我正在使用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)',因为没有对象

有人知道如何解决吗?

1个回答

5

有许多属性图的变体。其中一个是 transform_value_property_map,可以在这里使用。

C++03的简单方法

假设您使用C++03,则应编写:

在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

在 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()成员函数。 在Coliru上实时查看 你实际上不需要它。你可以直接编写Phoenix actor:
#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:

在Coliru上实时运行

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

在 Coliru 上添加了不少于 4 个实时示例 :) - sehe
非常感谢!还有一个问题:由于我没有使用C++11,并且想要并行调用Dijkstra算法(openMPI?)来计算三/四个K值,您认为哪种实现方式是最快的代码? - user1403546
1
无论常数K如何,最短路径应保持不变。假设图形在逻辑和位掩码方面是恒定的,您可以并行运行查询。 - sehe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接