Весовая карта как функция в алгоритме Boost Graph Дейкстры

Я использую 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;
}

Я бы хотел назвать алгоритм Дейкстры следующим образом:

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

Но ошибка в следующем

не может вызвать функцию-член «float Edge :: getWeight (int)» без
объект

Кто-нибудь знает как это решить?

4

Решение

Существует несколько разновидностей карты свойств. В частности, это transform_value_property_map можно использовать здесь.

Простой подход C ++ 03

Предполагая, что C ++ 03 вы бы написали:

Жить на Колиру

#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

Жить на Колиру

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() функция-член

Жить на Колиру

Тебе это не нужно. Вы можете написать актера Феникса на месте:

#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 снова:

Жить на Колиру

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

Другие решения

Других решений пока нет …