Class templates adjacency_list
and
adjacency_matrix
support
the introduction of named properties via internal
properties. However, this method is cumbersome in many uses,
where it would be more intuitive to just specify a structure or
class that contains internal properties for edges or
vertices. Bundled properties allow one to use
adjacency_list
and adjacency_matrix
in this
manner, providing a simple
way to introduce and access any number of internal properties
for vertices and edges.
One can introduce bundled properties into an
either graph type by providing a user-defined class
type for the VertexProperties
or
EdgeProperties
template arguments. The user-defined
class may alternatively be placed at the end of a
property
list, replacing the (implicit)
boost::no_property
argument.
Consider the implementation of a simple route planner that should find the shortest directions from one city to another via a set of highways. The vertices of the graph are cities, and we may wish to store several bits of information about the city within each vertex:
struct City { string name; int population; vector<int> zipcodes; };
The edges in the graph represent highways, which also have several interesting attributes:
struct Highway { string name; double miles; int speed_limit; int lanes; bool divided; };
Without bundled properties, translating this example directly
into an instantiation of adjacency_list
would
involve several custom properties and would result in a type
like this:
typedef boost::adjacency_list< boost::listS, boost::vecS, boost::bidirectionalS, // Vertex properties boost::property<boost::vertex_name_t, std::string, boost::property<population_t, int, boost::property<zipcodes_t, std::vector<int> > > >, // Edge properties boost::property<boost::edge_name_t, std::string, boost::property<boost::edge_length_t, double, boost::property<edge_speed_limit_t, int, boost::property<edge_lanes_t, int, boost::property<edge_divided, bool> > > > > > Map;
With bundled properties, we can directly use the
City
and Highway
structures:
typedef boost::adjacency_list< boost::listS, boost::vecS, boost::bidirectionalS, City, Highway> Map;
To access a bundled property for a particular edge or vertex, subscript your graph with the descriptor of the edge or vertex whose bundled property you wish to access. For instance:
Map map; // load the map Map::vertex_descriptor v = *vertices(map).first; map[v].name = "Troy"; map[v].population = 49170; map[v].zipcodes.push_back(12180); Map::edge_descriptor e = *out_edges(v, map).first; map[e].name = "I-87"; map[e].miles = 10; map[e].speed_limit = 65; map[e].lanes = 4; map[e].divided = true;
Often one needs to create a property map from an internal property for use in a generic algorithm. For instance, using the graph without bundled properties we might invoke Dijkstra's shortest paths algorithm like this:
vector<double> distances(num_vertices(map)); dijkstra_shortest_paths(map, from, weight_map(get(edge_length, map)) .distance_map(make_iterator_property_map(distances.begin(), get(vertex_index, map))));
With bundled properties, we can just pass a member pointer
as the property for get
. The equivalent example
using bundled properties is:
vector<double> distances(num_vertices(map)); dijkstra_shortest_paths(map, from, weight_map(get(&Highway::miles, map)) .distance_map(make_iterator_property_map(distances.begin(), get(vertex_index, map))));
The type of the returned property map is property_map<Map, int Highway::*>::type
or property_map<Map, int Highway::*>::const_type
, depending on whether the graph
map
is non-constant or constant.
You may also access the entire vertex or edge bundle as a property map
using the vertex_bundle
or edge_bundle
properties,
respectively. For instance, the property map returned by get(vertex_bundle, map)
is
an Lvalue Property Map providing access to the
City
values stored in each vertex.
To get the type of the vertex or edge bundle for a given graph type Graph, you can use the trait classes vertex_bundle_type and edge_bundle_type. The type vertex_bundle_type<Graph>::type will be the type bundled with vertices (or no_vertex_bundle if the graph supports bundles but no vertex bundle exists). Likewise, edge_bundle_type<Graph>::type will be the type bundled with edges (or no_edge_bundle if no edge bundle exists).
Bundled properties will only work properly on compilers that support class template partial specialization.