[英]boost::adjancency_list with polymorphic vertices and edges
我正在学习 BGL 并拼凑一个程序(来自各种相关的 StackOverflow 答案)来构建一个应该能够处理多态顶点和边的图形。 该图应该能够处理平行边(相同类型或不同类型)。 我想将dijkstra_shortest_paths
从起始vertex_descriptor
到: 1. 所有 Park 的; 2. 所有公园和城市的; 3. 仅限全市的铁路。 这甚至可能吗? 谢谢你。
#include <iostream>
#include <deque>
#include "boost/graph/adjacency_list.hpp"
#include "boost/graph/topological_sort.hpp"
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/variant.hpp>
#include <boost/graph/adj_list_serialize.hpp>
#include <boost/property_map/function_property_map.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
using namespace boost;
struct Highway {
std::string name;
int miles;
int speed_limit;
int lanes;
bool divided;
};
struct Railway {
std::string name;
int km;
};
struct City {
std::string name;
int population;
std::vector<int> zipcodes;
};
struct Park {
std::string name;
int population;
std::vector<int> zipcodes;
};
struct Country {
std::string name;
bool use_right; // Drive on the left or right
bool use_metric; // mph or km/h
};
int main(int argc, char *argv[]) {
typedef boost::adjacency_list<
boost::listS, boost::vecS, boost::bidirectionalS,
boost::variant<City, Park>, boost::variant<Highway, Railway>, Country>
Map;
City c1 = {"San Jose", 1200000, {95126, 95128}};
City c2 = {"San Francisco", 500000, {95008, 95009}};
City c3 = {"Santa Cruz", 300000, {94001, 94002}};
City c4 = {"Oakland", 800000, {93001, 93002}};
City c5 = {"San Diego", 2800000, {92001, 92002}};
Map map; // load the map
Map::vertex_descriptor c1d = boost::add_vertex(c1, map),
c2d = boost::add_vertex(c2, map),
c3d = boost::add_vertex(c3, map),
c4d = boost::add_vertex(c4, map),
c5d = boost::add_vertex(c5, map);
add_edge(c1d, c2d, Highway{"101", 42, 65, 3, true}, map);
add_edge(c2d, c3d, Highway{"280", 52, 60, 1, true}, map);
add_edge(c2d, c3d, Highway{"92", 13, 60, 1, true}, map);
//add_edge(c2, c3, map);
//add_edge(c1, c3, map);
map[graph_bundle].name = "United States";
map[graph_bundle].use_right = true;
map[graph_bundle].use_metric = false;
using vertex_descriptor = boost::graph_traits<Map>::vertex_descriptor;
Map::vertex_descriptor from = *vertices(map).first;
std::vector<int> distances(num_vertices(map));
auto v_index = get(boost::vertex_index, map);
auto v_bundle = get(boost::vertex_bundle, map);
dijkstra_shortest_paths(map, from,
weight_map(get(get(&Highway::miles, map))
.distance_map(make_iterator_property_map(distances.begin(),
get(vertex_index, map))));
std::cout << "distances and parents:" << std::endl;
graph_traits <Map>::vertex_iterator vi, vend;
for (boost::tie(vi, vend) = vertices(map); vi != vend; ++vi) {
std::cout << "distance(" << get<City>(&City::name, map[*vi]) << ") = " << distances[*vi] << ", " << "\n";
}
std::cout << std::endl;
return 0;
}
因此,简而言之,您希望从变体元素类型访问属性。 您可以创建自己的属性 map,方便您自己的访问器集或使用属性 map 适配器。
后者工作最少:
auto highway_miles = boost::make_transform_value_property_map(
[](Interconnect const& conn) {
if (auto* c = boost::get<Highway>(&conn)) {
return c->miles;
} else {
return std::numeric_limits<Distance>::max();
}
},
get(boost::edge_bundle, map));
dijkstra_shortest_paths(
map, from,
weight_map(highway_miles)
.distance_map(make_iterator_property_map(
distances.begin(), v_index)));
事实上,使用vecS
选择的顶点容器选择器,您可以更简洁地编写它:
dijkstra_shortest_paths(
map, from, weight_map(highway_miles).distance_map(distances.data()));
#include <deque>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/topological_sort.hpp>
#include <boost/property_map/function_property_map.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/variant.hpp>
using Distance = int;
struct Highway {
std::string name;
Distance miles;
unsigned speed_limit, lanes;
bool divided;
};
struct Railway {
std::string name;
Distance km;
};
struct City {
std::string name;
unsigned population;
std::vector<unsigned> zipcodes;
};
struct Park {
std::string name;
unsigned population;
std::vector<unsigned> zipcodes;
};
using Interconnect = boost::variant<Highway, Railway>;
using Area = boost::variant<City, Park>;
enum class RoadOrientation { right, left };
enum class UnitSystem { metric, imperial };
struct Country {
std::string name;
RoadOrientation driving;
UnitSystem measure;
};
using Map = boost::adjacency_list< //
boost::listS, boost::vecS, boost::bidirectionalS, //
Area, Interconnect, Country>;
int main()
{
Map map;
map[boost::graph_bundle] = {
"United States",
RoadOrientation::right,
UnitSystem::imperial,
};
auto c1d = add_vertex(City{"San Jose", 1200000, {95126, 95128}}, map);
auto c2d = add_vertex(City{"San Francisco", 500000, {95008, 95009}}, map);
auto c3d = add_vertex(City{"Santa Cruz", 300000, {94001, 94002}}, map);
add_vertex(City{"Oakland", 800000, {93001, 93002}}, map);
add_vertex(City{"San Diego", 2800000, {92001, 92002}}, map);
add_edge(c1d, c2d, Highway{"101", 42, 65, 3, true}, map);
add_edge(c2d, c3d, Highway{"280", 52, 60, 1, true}, map);
add_edge(c2d, c3d, Highway{"92", 13, 60, 1, true}, map);
using V = Map::vertex_descriptor;
V from = vertex(0, map);
std::vector<int> distances(num_vertices(map));
auto v_index = get(boost::vertex_index, map);
auto highway_miles = boost::make_transform_value_property_map(
[](Interconnect const& conn) {
if (auto* c = boost::get<Highway>(&conn)) {
return c->miles;
} else {
return std::numeric_limits<Distance>::max();
}
},
get(boost::edge_bundle, map));
dijkstra_shortest_paths(
map, from,
weight_map(highway_miles)
.distance_map(make_iterator_property_map(
distances.begin(), v_index)));
dijkstra_shortest_paths(
map, from, weight_map(highway_miles).distance_map(distances.data()));
std::cout << "distances and parents:" << std::endl;
auto name_of = [](auto const& area) {
return boost::apply_visitor(
[](auto const& c_or_p) { return c_or_p.name; }, area);
};
for (auto v : boost::make_iterator_range(vertices(map)))
std::cout << "distance(" << name_of(map[v]) << ") = " << distances[v] << "\n";
}
印刷
distances and parents:
distance(San Jose) = 0
distance(San Francisco) = 42
distance(Santa Cruz) = 55
distance(Oakland) = 2147483647
distance(San Diego) = 2147483647
我过去曾提供过建议/替代方案:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.