我是BGL的新手,并尝试使用BGL设置一个简单的最短路径查找程序,其中无向图被定义为具有自定义EdgeProperty和VertexProperty的邻接List。我收到编译时错误,这归因于我在模板和Boost中的技能不足。 代码如下:
<app-my-component></app-my-component>
错误是从double到EdgeProperty的未知转换。看来我在调用dijkstra_shortest_paths函数的语法上有错误。
我还想用一个函数替换EdgeProperty的数据成员。
我的其他查询是关于通过顶点描述符维护节点的索引。目前,我正在使用VertexProperty :: id做一个字典到VertexProperty类型的对象。 Do Boost在内部维护我可以使用的任何字典。
我在Ubuntu 16.04上使用gcc5.4版本编译器 谢谢
尼丁
答案 0 :(得分:1)
@llonesmiz是正确的。这是对代码和现场演示的一般清理。
我还使用make_transform_value_property_map
来使用getWeight()
并将所有数据成员设为私有。
注意我怀疑,因为您使用捆绑属性(?),
std::map
实例不再具有实用性。在任何情况下,如果您不再需要它们,可以删除一些代码: Shorter Demo注意您可能不了解
print_graph
。 Even Shorter ,稍微缩写输出
<强> Live On Coliru 强>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <iostream>
#include <map>
enum class Node_type { STAIR, LEVEL, LIFT, OTHER, UNKNOWN };
static std::ostream& operator<<(std::ostream& os, Node_type type) {
switch(type) {
case Node_type::STAIR: return os << "STAIR";
case Node_type::LEVEL: return os << "LEVEL";
case Node_type::LIFT: return os << "LIFT";
case Node_type::OTHER: return os << "OTHER";
default:
case Node_type::UNKNOWN: return os << "UNKNOWN";
}
}
class VertexProperty {
public:
VertexProperty(int id = -1, Node_type type = Node_type::UNKNOWN, int level_id=254, int stair_id=254)
: id(id), type(type), level_id(level_id), stair_id(stair_id) { }
std::string toString() const {
std::ostringstream oss;
oss << *this;
return oss.str();
}
int getVertexID() { return id; }
private:
friend std::ostream& operator<<(std::ostream& os, VertexProperty const& v) {
return os << "id " << v.id << " type " << v.type << " level " << v.level_id << " stair_id " << v.stair_id;
}
int id;
Node_type type;
int level_id;
int stair_id;
};
class EdgeProperty {
public:
EdgeProperty(int i = -1, double wt = 0) : id(i), weight(wt) {
id = i;
weight = wt;
}
double getWeight() { return weight; }
int getID() { return id; }
std::string toString() const {
std::ostringstream oss;
oss << *this;
return oss.str();
}
private:
friend std::ostream& operator<<(std::ostream& os, EdgeProperty const& e) {
return os << "id " << e.id << " weight=" << std::fixed << e.weight;
}
int id;
double weight;
};
class A {
public:
void undirected_graph_creation();
void showEdges();
void showVertices();
void runDijstra();
private:
typedef boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS, VertexProperty, EdgeProperty> UndirectedGraph;
UndirectedGraph g;
using edge_iterator = UndirectedGraph::edge_iterator;
using vertex_iterator = UndirectedGraph::vertex_iterator;
using vertex_descriptor = UndirectedGraph::vertex_descriptor;
using edge_descriptor = UndirectedGraph::edge_descriptor;
std::map<int, vertex_descriptor> map_id_vertex_desc;
std::map<int, edge_descriptor> map_id_edge_desc;
std::map<int, Node_type> map_node_id_type;
};
void A::undirected_graph_creation() {
auto add_vertex = [this](int id, Node_type type) {
// TODO: these maps are probably not required anymore
map_node_id_type[id] = type;
vertex_descriptor vd = boost::add_vertex(VertexProperty{id, type}, g);
return map_id_vertex_desc[id] = vd;
};
auto v0 = add_vertex(0, Node_type::LEVEL);
auto v1 = add_vertex(1, Node_type::STAIR);
auto v2 = add_vertex(2, Node_type::STAIR);
auto v3 = add_vertex(3, Node_type::STAIR);
auto add_edge = [this](vertex_descriptor u, vertex_descriptor v, EdgeProperty prop) {
auto ins = boost::add_edge(u, v, prop, g);
if (ins.second)
map_id_edge_desc[prop.getID()] = ins.first;
return ins.first;
};
add_edge(v0, v1, {1, 8});
add_edge(v0, v3, {2, 18});
add_edge(v1, v2, {3, 20});
add_edge(v2, v3, {4, 2});
add_edge(v1, v3, {5, 7});
}
void A::showEdges() {
for (auto e : boost::make_iterator_range(boost::edges(g)))
std::cout << "Edge " << e << " " << g[e] << "\n";
}
void A::showVertices() {
for (auto v : boost::make_iterator_range(boost::vertices(g)))
std::cout << "Vertex " << v << " " << g[v] << "\n";
}
void A::runDijstra() {
std::vector<vertex_descriptor> predecessors(num_vertices(g));
std::vector<double> distances(num_vertices(g));
vertex_descriptor start = *(vertices(g).first);
auto v_index = get(boost::vertex_index, g);
auto weight = boost::make_transform_value_property_map(std::mem_fn(&EdgeProperty::getWeight), get(boost::edge_bundle, g));
dijkstra_shortest_paths(
g, start,
predecessor_map(make_iterator_property_map(predecessors.begin(), v_index))
.distance_map(make_iterator_property_map(distances.begin(), v_index))
.weight_map(weight));
std::cout << "distances and parents:\n";
for (auto v : boost::make_iterator_range(boost::vertices(g))) {
auto id = g[v].getVertexID();
std::cout << "distance(" << id << ") = " << distances[v] << ", ";
std::cout << "parent(" << id << ") = " << g[predecessors[v]] << "\n";
}
}
int main() {
A a;
a.undirected_graph_creation();
a.showEdges();
a.showVertices();
a.runDijstra();
}
打印:
Edge (0,1) id 1 weight=8.000000
Edge (0,3) id 2 weight=18.000000
Edge (1,2) id 3 weight=20.000000
Edge (2,3) id 4 weight=2.000000
Edge (1,3) id 5 weight=7.000000
Vertex 0 id 0 type LEVEL level 254 stair_id 254
Vertex 1 id 1 type STAIR level 254 stair_id 254
Vertex 2 id 2 type STAIR level 254 stair_id 254
Vertex 3 id 3 type STAIR level 254 stair_id 254
distances and parents:
distance(0) = 0.000000, parent(0) = id 0 type LEVEL level 254 stair_id 254
distance(1) = 8.000000, parent(1) = id 0 type LEVEL level 254 stair_id 254
distance(2) = 17.000000, parent(2) = id 3 type STAIR level 254 stair_id 254
distance(3) = 15.000000, parent(3) = id 1 type STAIR level 254 stair_id 254