| [29] | 1 | <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> | 
|---|
 | 2 | <html> | 
|---|
 | 3 | <!-- | 
|---|
 | 4 | --  Copyright Doug Gregor 2004. Use, modification and | 
|---|
 | 5 | --  distribution is subject to the Boost Software License, Version | 
|---|
 | 6 | --  1.0. (See accompanying file LICENSE_1_0.txt or copy at | 
|---|
 | 7 | --  http://www.boost.org/LICENSE_1_0.txt) | 
|---|
 | 8 |  | 
|---|
 | 9 | -- For more information, see http://www.boost.org | 
|---|
 | 10 | --> | 
|---|
 | 11 |   <head> | 
|---|
 | 12 |     <title>Bundled Properties</title> | 
|---|
 | 13 |   </head> | 
|---|
 | 14 |  | 
|---|
 | 15 |   <body BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"  | 
|---|
 | 16 |         ALINK="#ff0000"> | 
|---|
 | 17 |     <IMG SRC="../../../boost.png"  | 
|---|
 | 18 |       ALT="C++ Boost" width="277" height="86"/>  | 
|---|
 | 19 |     <h1>Bundled Properties</h1> | 
|---|
 | 20 |  | 
|---|
 | 21 |       <p>Class templates <code><a | 
|---|
 | 22 |       href="adjacency_list.html">adjacency_list</a></code> and  | 
|---|
 | 23 |           <code><a href="adjacency_matrix.html">adjacency_matrix</a></code> support | 
|---|
 | 24 |       the introduction of named properties via <a | 
|---|
 | 25 |       href="using_adjacency_list.html#sec:adjacency-list-properties">internal | 
|---|
 | 26 |       properties</a>. However, this method is cumbersome in many uses, | 
|---|
 | 27 |       where it would be more intuitive to just specify a structure or | 
|---|
 | 28 |       class that contains internal properties for edges or | 
|---|
 | 29 |       vertices. Bundled properties allow one to use | 
|---|
 | 30 |       <code>adjacency_list</code> and <code>adjacency_matrix</code> in this  | 
|---|
 | 31 |           manner, providing a simple | 
|---|
 | 32 |       way to introduce and access any number of internal properties | 
|---|
 | 33 |       for vertices and edges.</p> | 
|---|
 | 34 |  | 
|---|
 | 35 |       <p>One can introduce bundled properties into an | 
|---|
 | 36 |       either graph type by providing a user-defined class | 
|---|
 | 37 |       type for the <code>VertexProperties</code> or | 
|---|
 | 38 |       <code>EdgeProperties</code> template arguments. The user-defined | 
|---|
 | 39 |       class may alternatively be placed at the end of a | 
|---|
 | 40 |       <code>property</code> list, replacing the (implicit) | 
|---|
 | 41 |       <code>boost::no_property</code> argument.</p> | 
|---|
 | 42 |  | 
|---|
 | 43 |       <h2>Example: Route planning</h2> | 
|---|
 | 44 |       <p>Consider the implementation of a simple route planner that | 
|---|
 | 45 |         should find the shortest directions from one city to another | 
|---|
 | 46 |         via a set of highways. The vertices of the graph are cities, | 
|---|
 | 47 |         and we may wish to store several bits of information about the | 
|---|
 | 48 |         city within each vertex:</p> | 
|---|
 | 49 |       <pre> | 
|---|
 | 50 | struct City | 
|---|
 | 51 | { | 
|---|
 | 52 |   string name; | 
|---|
 | 53 |   int population; | 
|---|
 | 54 |   vector<int> zipcodes; | 
|---|
 | 55 | }; | 
|---|
 | 56 |       </pre> | 
|---|
 | 57 |        | 
|---|
 | 58 |       <p>The edges in the graph represent highways, which also have | 
|---|
 | 59 |         several interesting attributes:</p> | 
|---|
 | 60 |  | 
|---|
 | 61 |       <pre> | 
|---|
 | 62 | struct Highway | 
|---|
 | 63 | { | 
|---|
 | 64 |   string name; | 
|---|
 | 65 |   double miles; | 
|---|
 | 66 |   int speed_limit; | 
|---|
 | 67 |   int lanes; | 
|---|
 | 68 |   bool divided; | 
|---|
 | 69 | }; | 
|---|
 | 70 |       </pre> | 
|---|
 | 71 |  | 
|---|
 | 72 |       <p>Without bundled properties, translating this example directly | 
|---|
 | 73 |       into an instantiation of <code>adjacency_list</code> would | 
|---|
 | 74 |       involve several custom properties and would result in a type | 
|---|
 | 75 |       like this:</p> | 
|---|
 | 76 |       <pre> | 
|---|
 | 77 | typedef boost::adjacency_list< | 
|---|
 | 78 |     boost::listS, boost::vecS, boost::bidirectionalS, | 
|---|
 | 79 |     // Vertex properties | 
|---|
 | 80 |     boost::property<boost::vertex_name_t, std::string,  | 
|---|
 | 81 |     boost::property<population_t, int, | 
|---|
 | 82 |     boost::property<zipcodes_t, std::vector<int> > > >, | 
|---|
 | 83 |     // Edge properties | 
|---|
 | 84 |     boost::property<boost::edge_name_t, std::string, | 
|---|
 | 85 |     boost::property<boost::edge_length_t, double, | 
|---|
 | 86 |     boost::property<edge_speed_limit_t, int, | 
|---|
 | 87 |     boost::property<edge_lanes_t, int, | 
|---|
 | 88 |     boost::property<edge_divided, bool> > > > > > | 
|---|
 | 89 |   Map; | 
|---|
 | 90 |       </pre> | 
|---|
 | 91 |  | 
|---|
 | 92 |       <p>With bundled properties, we can directly use the | 
|---|
 | 93 |         <code>City</code> and <code>Highway</code> structures:</p> | 
|---|
 | 94 |       <pre> | 
|---|
 | 95 | typedef boost::adjacency_list< | 
|---|
 | 96 |     boost::listS, boost::vecS, boost::bidirectionalS, | 
|---|
 | 97 |     City, Highway> Map; | 
|---|
 | 98 |       </pre> | 
|---|
 | 99 |  | 
|---|
 | 100 |     <h2>Accessing bundled properties</h2> | 
|---|
 | 101 |     <p>To access a bundled property for a particular edge or vertex, | 
|---|
 | 102 |         subscript your graph with the descriptor of the edge or vertex | 
|---|
 | 103 |         whose bundled property you wish to access. For instance:</p> | 
|---|
 | 104 |     <pre> | 
|---|
 | 105 | Map map; // load the map | 
|---|
 | 106 | Map::vertex_descriptor v = *vertices(map).first; | 
|---|
 | 107 | map[v].name = "Troy"; | 
|---|
 | 108 | map[v].population = 49170; | 
|---|
 | 109 | map[v].zipcodes.push_back(12180); | 
|---|
 | 110 | Map::edge_descriptor e = *out_edges(v, map).first; | 
|---|
 | 111 | map[e].name = "I-87"; | 
|---|
 | 112 | map[e].miles = 10; | 
|---|
 | 113 | map[e].speed_limit = 65; | 
|---|
 | 114 | map[e].lanes = 4; | 
|---|
 | 115 | map[e].divided = true; | 
|---|
 | 116 |     </pre> | 
|---|
 | 117 |  | 
|---|
 | 118 |     <h2>Properties maps from bundled properties</h2> | 
|---|
 | 119 |     <p>Often one needs to create a property map from an internal | 
|---|
 | 120 |       property for use in a generic algorithm. For instance, using the | 
|---|
 | 121 |       graph without bundled properties we might invoke <a | 
|---|
 | 122 |         href="dijkstra_shortest_paths.html">Dijkstra's shortest | 
|---|
 | 123 |         paths</a> algorithm like this:</p> | 
|---|
 | 124 |     <pre> | 
|---|
 | 125 | vector<double> distances(num_vertices(map)); | 
|---|
 | 126 | dijkstra_shortest_paths(map, from, | 
|---|
 | 127 |       weight_map(get(edge_length, map)) | 
|---|
 | 128 |       .distance_map(make_iterator_property_map(distances.begin(), | 
|---|
 | 129 |                                                get(vertex_index, map)))); | 
|---|
 | 130 |     </pre> | 
|---|
 | 131 |  | 
|---|
 | 132 |     <p>With bundled properties, we can just pass a <em>member pointer</em> | 
|---|
 | 133 |           as the property for <code>get</code>. The equivalent example | 
|---|
 | 134 |       using bundled properties is:</p> | 
|---|
 | 135 |     <pre> | 
|---|
 | 136 | vector<double> distances(num_vertices(map)); | 
|---|
 | 137 | dijkstra_shortest_paths(map, from, | 
|---|
 | 138 |       weight_map(get(<font color="#ff0000">&Highway::miles</font>, map)) | 
|---|
 | 139 |       .distance_map(make_iterator_property_map(distances.begin(), | 
|---|
 | 140 |                                                get(vertex_index, map)))); | 
|---|
 | 141 |     </pre> | 
|---|
 | 142 |  | 
|---|
 | 143 |     <p>The type of the returned property map is <code>property_map<Map, int Highway::*>::type</code>  | 
|---|
 | 144 |         or <code>property_map<Map, int Highway::*>::const_type</code>, depending on whether the graph  | 
|---|
 | 145 |         <code>map</code> is non-constant or constant. | 
|---|
 | 146 |          | 
|---|
 | 147 |     <p> You may also access the entire vertex or edge bundle as a property map  | 
|---|
 | 148 |         using the <code>vertex_bundle</code> or <code>edge_bundle</code> properties, | 
|---|
 | 149 |         respectively. For instance, the property map returned by <code>get(vertex_bundle, map)</code> is | 
|---|
 | 150 |         an <a href="../../property_map/LvaluePropertyMap.html">Lvalue Property Map</a> providing access to the | 
|---|
 | 151 |         <code>City</code> values stored in each vertex. | 
|---|
 | 152 |  | 
|---|
 | 153 |     <h2>Getting the type of bundled properties</h2> | 
|---|
 | 154 |  | 
|---|
 | 155 |     <p>To get the type of the vertex or edge bundle for a given graph | 
|---|
 | 156 |     type <tt>Graph</tt>, you can use the trait | 
|---|
 | 157 |     classes <tt>vertex_bundle_type</tt> | 
|---|
 | 158 |     and <tt>edge_bundle_type</tt>. The | 
|---|
 | 159 |     type <tt>vertex_bundle_type<Graph>::type</tt> will be the | 
|---|
 | 160 |     type bundled with vertices (or <tt>no_vertex_bundle</tt> if the | 
|---|
 | 161 |     graph supports bundles but no vertex bundle | 
|---|
 | 162 |     exists). Likewise, <tt>edge_bundle_type<Graph>::type</tt> | 
|---|
 | 163 |     will be the type bundled with edges (or <tt>no_edge_bundle</tt> if | 
|---|
 | 164 |     no edge bundle exists).</p> | 
|---|
 | 165 |  | 
|---|
 | 166 |     <h2>Compatibility</h2> <p>Bundled properties will only work | 
|---|
 | 167 |     properly on compilers that support class template partial | 
|---|
 | 168 |     specialization.</p> | 
|---|
 | 169 |  | 
|---|
 | 170 |     <hr> | 
|---|
 | 171 | Copyright © 2004 <a href="../../../people/doug_gregor.html">Doug Gregor</a>. | 
|---|
 | 172 |     <address><a href="mailto:gregod@cs.rpi.edu"></a></address> | 
|---|
 | 173 | <!-- Created: Fri May  7 09:59:21 EDT 2004 --> | 
|---|
 | 174 | <!-- hhmts start --> | 
|---|
 | 175 | Last modified: Fri May  7 10:56:01 EDT 2004 | 
|---|
 | 176 | <!-- hhmts end --> | 
|---|
 | 177 |   </body> | 
|---|
 | 178 | </html> | 
|---|