compressed_sparse_row.html 43 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2. <html>
  3. <!--
  4. Copyright (c) 2005-2009 Trustees of Indiana University
  5. Distributed under the Boost Software License, Version 1.0.
  6. (See accompanying file LICENSE_1_0.txt or copy at
  7. http://www.boost.org/LICENSE_1_0.txt)
  8. -->
  9. <head>
  10. <title>Compressed Sparse Row Graph</title>
  11. <STYLE TYPE="text/css">
  12. <!--
  13. .indent
  14. {
  15. padding-left: 50pt;
  16. padding-right: 50pt;
  17. }
  18. -->
  19. </STYLE>
  20. <script language="JavaScript" type="text/JavaScript">
  21. <!--
  22. function address(host, user) {
  23. var atchar = '@';
  24. var thingy = user+atchar+host;
  25. thingy = '<a hre' + 'f=' + "mai" + "lto:" + thingy + '>' + user+atchar+host + '</a>';
  26. document.write(thingy);
  27. }
  28. //-->
  29. </script>
  30. </head>
  31. <body>
  32. <IMG SRC="../../../boost.png"
  33. ALT="C++ Boost" width="277" height="86"></img>
  34. <h1>Compressed Sparse Row Graph</h1>
  35. <p>The class template <code>compressed_sparse_row_graph</code> is
  36. a graph class that uses the compact Compressed Sparse Row (CSR)
  37. format to store directed (and bidirectional) graphs. While CSR graphs have
  38. much less
  39. overhead than many other graph formats (e.g., <a
  40. href="adjacency_list.html"><code>adjacency_list</code></a>), they
  41. do not provide any mutability: one cannot add or remove vertices
  42. or edges from a CSR graph. Use this format in high-performance
  43. applications or for very large graphs that you do not need to
  44. change.</p>
  45. <p>The CSR format stores vertices and edges in separate arrays,
  46. with the indices into these arrays corresponding to the identifier
  47. for the vertex or edge, respectively. The edge array is sorted by
  48. the source of each edge, but contains only the targets for the
  49. edges. The vertex array stores offsets into the edge array,
  50. providing the offset of the first edge outgoing from each
  51. vertex. Iteration over the out-edges for the <i>i</i><sup>th</sup>
  52. vertex in the graph is achieved by
  53. visiting <tt>edge_array[vertex_array[i]]</tt>,
  54. <tt>edge_array[vertex_array[i]+1]</tt>,
  55. ..., <tt>edge_array[vertex_array[i+1]]</tt>. This format minimizes
  56. memory use to <i>O(n + m)</i>, where <i>n</i> and <i>m</i> are the
  57. number of vertices and edges, respectively. The constants
  58. multiplied by <i>n</i> and <i>m</i> are based on the size of the
  59. integers needed to represent indices into the edge and vertex
  60. arrays, respectively, which can be controlled using
  61. the <a href="#template-parms">template parameters</a>. The
  62. <tt>Directed</tt> template parameter controls whether one edge direction
  63. (the default) or both directions are stored. A directed CSR graph has
  64. <tt>Directed</tt> = <tt>directedS</tt> and a bidirectional CSR graph (with
  65. a limited set of constructors)
  66. has <tt>Directed</tt> = <tt>bidirectionalS</tt>.</p>
  67. <ul>
  68. <li><a href="#synopsis">Synopsis</a></li>
  69. <li><a href="#where">Where Defined</a></li>
  70. <li><a href="#models">Models</a></li>
  71. <li><a href="#template-parms">Template parameters</a></li>
  72. <li><a href="#properties">Properties</a></li>
  73. <li><a href="#member-functions">Member functions</a>
  74. <ul>
  75. <li><a href="#constructors">Constructors</a></li>
  76. <li><a href="#mutators">Mutators</a></li>
  77. <li><a href="#property-access">Property access</a></li>
  78. </ul></li>
  79. <li><a href="#non-members">Non-member functions</a>
  80. <ul>
  81. <li><a href="#vertex-access">Vertex access</a></li>
  82. <li><a href="#edge-access">Edge access</a></li>
  83. <li><a href="#property-map-accessors">Property map accessors</a></li>
  84. <li><a href="#incremental-construction-functions">Incremental construction functions</a></li>
  85. </ul></li>
  86. <li><a href="#example">Example</a></li>
  87. </ul>
  88. <a name="synopsis"></a><h2>Synopsis</h2>
  89. <pre>
  90. namespace boost {
  91. template&lt;typename <a href="#Directed">Directed</a> = directedS, typename <a href="#VertexProperty">VertexProperty</a> = no_property,
  92. typename <a href="#EdgeProperty">EdgeProperty</a> = no_property, typename <a href="#GraphProperty">GraphProperty</a> = no_property,
  93. typename <a href="#Vertex">Vertex</a> = std::size_t, typename <a href="#EdgeIndex">EdgeIndex</a> = Vertex&gt;
  94. class compressed_sparse_row_graph
  95. {
  96. public:
  97. <i>// <a href="#constructors">Graph constructors</a></i>
  98. <a href="#default-const">compressed_sparse_row_graph</a>();
  99. <i>// Unsorted edge list constructors </i>
  100. template&lt;typename InputIterator&gt;
  101. <a href="#edge-const">compressed_sparse_row_graph</a>(edges_are_unsorted_t,
  102. InputIterator edge_begin, InputIterator edge_end,
  103. vertices_size_type numverts,
  104. const GraphProperty&amp; prop = GraphProperty());
  105. template&lt;typename InputIterator, typename EdgePropertyIterator&gt;
  106. <a href="#edge-prop-const">compressed_sparse_row_graph</a>(edges_are_unsorted_t,
  107. InputIterator edge_begin, InputIterator edge_end,
  108. EdgePropertyIterator ep_iter,
  109. vertices_size_type numverts,
  110. const GraphProperty&amp; prop = GraphProperty());
  111. template&lt;typename MultiPassInputIterator&gt;
  112. <a href="#edge-multi-const">compressed_sparse_row_graph</a>(edges_are_unsorted_multi_pass_t,
  113. MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
  114. vertices_size_type numverts,
  115. const GraphProperty&amp; prop = GraphProperty());
  116. template&lt;typename MultiPassInputIterator, typename EdgePropertyIterator&gt;
  117. <a href="#edge-multi-prop-const">compressed_sparse_row_graph</a>(edges_are_unsorted_multi_pass_t,
  118. MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
  119. EdgePropertyIterator ep_iter,
  120. vertices_size_type numverts,
  121. const GraphProperty&amp; prop = GraphProperty());
  122. <i>// New sorted edge list constructors <b>(directed only)</b></i>
  123. template&lt;typename InputIterator&gt;
  124. <a href="#edge-sorted-const">compressed_sparse_row_graph</a>(edges_are_sorted_t,
  125. InputIterator edge_begin, InputIterator edge_end,
  126. vertices_size_type numverts,
  127. edges_size_type numedges = 0,
  128. const GraphProperty&amp; prop = GraphProperty());
  129. template&lt;typename InputIterator, typename EdgePropertyIterator&gt;
  130. <a href="#edge-sorted-prop-const">compressed_sparse_row_graph</a>(edges_are_sorted_t,
  131. InputIterator edge_begin, InputIterator edge_end,
  132. EdgePropertyIterator ep_iter,
  133. vertices_size_type numverts,
  134. edges_size_type numedges = 0,
  135. const GraphProperty&amp; prop = GraphProperty());
  136. <i>// In-place unsorted edge list constructors <b>(directed only)</b></i>
  137. template&lt;typename InputIterator&gt;
  138. <a href="#edge-inplace-const">compressed_sparse_row_graph</a>(construct_inplace_from_sources_and_targets_t,
  139. std::vector&lt;vertex_descriptor&gt;&amp; sources,
  140. std::vector&lt;vertex_descriptor&gt;&amp; targets,
  141. vertices_size_type numverts,
  142. const GraphProperty&amp; prop = GraphProperty());
  143. template&lt;typename InputIterator&gt;
  144. <a href="#edge-inplace-prop-const">compressed_sparse_row_graph</a>(construct_inplace_from_sources_and_targets_t,
  145. std::vector&lt;vertex_descriptor&gt;&amp; sources,
  146. std::vector&lt;vertex_descriptor&gt;&amp; targets,
  147. std::vector&lt;EdgeProperty&gt;&amp; edge_props,
  148. vertices_size_type numverts,
  149. const GraphProperty&amp; prop = GraphProperty());
  150. <i>// Miscellaneous constructors <b>(directed only)</b></i>
  151. template&lt;typename Graph, typename VertexIndexMap&gt;
  152. <a href="#graph-const">compressed_sparse_row_graph</a>(const Graph&amp; g, const VertexIndexMap&amp; vi,
  153. vertices_size_type numverts,
  154. edges_size_type numedges);
  155. template&lt;typename Graph, typename VertexIndexMap&gt;
  156. compressed_sparse_row_graph(const Graph&amp; g, const VertexIndexMap&amp; vi);
  157. template&lt;typename Graph&gt;
  158. explicit <a href="#graph-const">compressed_sparse_row_graph</a>(const Graph&amp; g);
  159. <i>// <a href="#mutators">Graph mutators <b>(directed only)</b></a></i>
  160. template&lt;typename Graph, typename VertexIndexMap&gt;
  161. void <a href="#assign">assign</a>(const Graph&amp; g, const VertexIndexMap&amp; vi,
  162. vertices_size_type numverts, edges_size_type numedges);
  163. template&lt;typename Graph, typename VertexIndexMap&gt;
  164. void <a href="#assign">assign</a>(const Graph&amp; g, const VertexIndexMap&amp; vi);
  165. template&lt;typename Graph&gt;
  166. void <a href="#assign">assign</a>(const Graph&amp; g);
  167. <i>// <a href="#property-access">Property Access</a></i>
  168. VertexProperty&amp; <a href="#vertex-subscript">operator[]</a>(vertex_descriptor v);
  169. const VertexProperty&amp; <a href="#vertex-subscript">operator[]</a>(vertex_descriptor v) const;
  170. EdgeProperty&amp; <a href="#edge-subscript">operator[]</a>(edge_descriptor v);
  171. const EdgeProperty&amp; <a href="#edge-subscript">operator[]</a>(edge_descriptor v) const;
  172. };
  173. <i>// <a href="IncidenceGraph.html">Incidence Graph requirements</a></i>
  174. vertex_descriptor source(edge_descriptor, const compressed_sparse_row_graph&amp;);
  175. vertex_descriptor target(edge_descriptor, const compressed_sparse_row_graph&amp;);
  176. std::pair&lt;out_edge_iterator, out_edge_iterator&gt;
  177. out_edges(vertex_descriptor, const compressed_sparse_row_graph&amp;);
  178. degree_size_type out_degree(vertex_descriptor v, const compressed_sparse_row_graph&amp;);
  179. <i>// <a href="BidirectionalGraph.html">Bidirectional Graph requirements <b>(bidirectional only)</b></a></i>
  180. std::pair&lt;in_edge_iterator, in_edge_iterator&gt;
  181. in_edges(vertex_descriptor, const compressed_sparse_row_graph&amp;);
  182. degree_size_type in_degree(vertex_descriptor v, const compressed_sparse_row_graph&amp;);
  183. <i>// <a href="AdjacencyGraph.html">Adjacency Graph requirements</a></i>
  184. std::pair&lt;adjacency_iterator, adjacency_iterator&gt;
  185. adjacent_vertices(vertex_descriptor, const compressed_sparse_row_graph&amp;);
  186. <i>// <a href="VertexListGraph.html">Vertex List Graph requirements</a></i>
  187. std::pair&lt;vertex_iterator, vertex_iterator&gt; vertices(const compressed_sparse_row_graph&amp;);
  188. vertices_size_type num_vertices(const compressed_sparse_row_graph&amp;);
  189. <i>// <a href="EdgeListGraph.html">Edge List Graph requirements</a></i>
  190. std::pair&lt;edge_iterator, edge_iterator&gt; edges(const compressed_sparse_row_graph&amp;);
  191. edges_size_type num_edges(const compressed_sparse_row_graph&amp;);
  192. <i>// <a href="#vertex-access">Vertex access</a></i>
  193. vertex_descriptor <a href="#vertex-lookup">vertex</a>(vertices_size_type i, const compressed_sparse_row_graph&amp;);
  194. <i>// <a href="#edge-access">Edge access</a></i>
  195. std::pair&lt;edge_descriptor, bool&gt;
  196. <a href="#edge">edge</a>(vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&amp;);
  197. edge_descriptor <a href="#edge_from_index">edge_from_index</a>(edges_size_type i, const compressed_sparse_row_graph&amp;);
  198. <i>// <a href="#property-map-accessors">Property map accessors</a></i>
  199. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>&gt;
  200. property_map&lt;compressed_sparse_row_graph, PropertyTag&gt;::type
  201. <a href="#get">get</a>(PropertyTag, compressed_sparse_row_graph&amp; g)
  202. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>&gt;
  203. property_map&lt;compressed_sparse_row_graph, Tag&gt;::const_type
  204. <a href="#get">get</a>(PropertyTag, const compressed_sparse_row_graph&amp; g)
  205. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>, class X&gt;
  206. typename property_traits&lt;property_map&lt;compressed_sparse_row_graph, PropertyTag&gt;::const_type&gt;::value_type
  207. <a href="#get-x">get</a>(PropertyTag, const compressed_sparse_row_graph&amp; g, X x)
  208. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>, class X, class Value&gt;
  209. void <a href="#put-x">put</a>(PropertyTag, const compressed_sparse_row_graph&amp; g, X x, const Value&amp; value);
  210. template&lt;typename <a href="./PropertyTag.html#GraphPropertyTag">GraphPropertyTag</a>&gt;
  211. typename graph_property&lt;compressed_sparse_row_graph, GraphPropertyTag&gt;::type&amp;
  212. <a href="#get_property">get_property</a>(compressed_sparse_row_graph&amp; g, GraphPropertyTag);
  213. template&lt;typename <a href="./PropertyTag.html#GraphPropertyTag">GraphPropertyTag</a>&gt;
  214. typename graph_property&lt;compressed_sparse_row_graph, GraphPropertyTag&gt;::type const &amp;
  215. <a href="#get_property">get_property</a>(const compressed_sparse_row_graph&amp; g, GraphPropertyTag);
  216. template&lt;typename <a href="./PropertyTag.html#GraphPropertyTag">GraphPropertyTag</a>&gt;
  217. void <a href="#set_property">set_property</a>(const compressed_sparse_row_graph&amp; g, GraphPropertyTag,
  218. const typename graph_property&lt;compressed_sparse_row_graph, GraphPropertyTag&gt;::type&amp; value);
  219. <i>// <a href="#incremental-construction-functions">Incremental construction functions</a></i>
  220. <b>(directed only)</b>
  221. template&lt;typename InputIterator, typename Graph&gt;
  222. void <a href="#add_edges">add_edges</a>(InputIterator first, InputIterator last, compressed_sparse_row_graph&amp; g);
  223. <b>(directed only)</b>
  224. template&lt;typename InputIterator, typename EPIter, typename Graph&gt;
  225. void <a href="#add_edges_prop">add_edges</a>(InputIterator first, InputIterator last, EPIter ep_first, EPIter ep_last, compressed_sparse_row_graph&amp; g);
  226. <b>(directed only)</b>
  227. template&lt;typename BidirectionalIterator, typename Graph&gt;
  228. void <a href="#add_edges_sorted">add_edges_sorted</a>(BidirectionalIterator first, BidirectionalIterator last, compressed_sparse_row_graph&amp; g);
  229. <b>(directed only)</b>
  230. template&lt;typename BidirectionalIterator, typename EPIter, typename Graph&gt;
  231. void <a href="#add_edges_sorted_prop">add_edges_sorted</a>(BidirectionalIterator first, BidirectionalIterator last, EPIter ep_iter, compressed_sparse_row_graph&amp; g);
  232. } <i>// end namespace boost</i>
  233. </pre>
  234. <a name="where"></a><h2>Where Defined</h2>
  235. <p><code>&lt;<a href="../../../boost/graph/compressed_sparse_row_graph.hpp">boost/graph/compressed_sparse_row_graph.hpp</a>&gt;</code></p>
  236. <a name="models"></a><h2>Models</h2>
  237. <p>The <tt>compressed_sparse_row_graph</tt> class template models
  238. (i.e., implements the requirements of) many of the
  239. BGL <a href="graph_concepts.html">graph concepts</a>, allowing it
  240. to be used with most of the BGL algorithms. In particular, it
  241. models the following specific graph concepts:</p>
  242. <ul>
  243. <li><a href="Graph.html">Graph</a></li>
  244. <li><a href="IncidenceGraph.html">IncidenceGraph</a></li>
  245. <li><a href="AdjacencyGraph.html">AdjacencyGraph</a></li>
  246. <li><a href="VertexListGraph.html">VertexListGraph</a></li>
  247. <li><a href="EdgeListGraph.html">EdgeListGraph</a></li>
  248. <li><a href="PropertyGraph.html">PropertyGraph</a></li>
  249. </ul>
  250. <a name="template-parms"></a><h2>Template Parameters</h2>
  251. <p>The <tt>compressed_sparse_row_graph</tt> class has several
  252. template parameters that can customize the layout in memory and
  253. what properties are attached to the graph itself. All
  254. parameters have defaults, so users interested only in the
  255. structure of a graph can use the
  256. type <tt>compressed_sparse_row_graph&lt;&gt;</tt> and ignore
  257. the parameters.</p>
  258. <b>Parameters</b>
  259. <br>
  260. <br>
  261. <a name="Directed"></a><code>Directed</code>
  262. <blockquote>
  263. A selector that determines whether the graph will be directed,
  264. bidirectional or undirected. At this time, the CSR graph type
  265. only supports directed and bidirectional graphs, so this value must
  266. be either <code>boost::directedS</code> or
  267. <code>boost::bidirectionalS</code>.<br>
  268. <b>Default</b>: <code>boost::directedS</code>
  269. </blockquote>
  270. <a name="VertexProperty"></a><code>VertexProperty</code>
  271. <blockquote>
  272. A class type that will be
  273. attached to each vertex in the graph. If this value
  274. is <code>void</code>, no properties will be attached to
  275. the vertices of the graph.<br>
  276. <b>Default</b>: <code>void</code>
  277. </blockquote>
  278. <a name="EdgeProperty"></a><code>EdgeProperty</code>
  279. <blockquote>
  280. A class type that will be attached to each edge in the graph. If
  281. this value is <code>void</code>, no properties will be
  282. attached to the edges of the graph.<br>
  283. <b>Default</b>: <code>void</code>
  284. </blockquote>
  285. <a name="GraphProperty"></a><code>GraphProperty</code>
  286. <blockquote>
  287. A nested set
  288. of <code>property</code> templates that describe the
  289. properties of the graph itself. If this value
  290. is <code>no_property</code>, no properties will be attached to
  291. the graph.<br>
  292. <b>Default</b>: <code>no_property</code>
  293. </blockquote>
  294. <a name="Vertex"></a><code>Vertex</code>
  295. <blockquote>
  296. An unsigned integral type that will be
  297. used as both the index into the array of vertices and as the
  298. vertex descriptor itself. Larger types permit the CSR graph to
  299. store more vertices; smaller types reduce the storage required
  300. per vertex.<br>
  301. <b>Default</b>: <code>std::size_t</code>
  302. </blockquote>
  303. <a name="EdgeIndex"></a><code>EdgeIndex</code>
  304. <blockquote>
  305. An unsigned integral type that will be used as the index into
  306. the array of edges. As with the <code>Vertex</code> parameter,
  307. larger types permit more edges whereas smaller types reduce
  308. the amount of storage needed per
  309. edge. The <code>EdgeIndex</code> type shall not be smaller
  310. than the <code>Vertex</code> type, but it may be larger. For
  311. instance, <code>Vertex</code> may be a 16-bit integer
  312. (allowing 32,767 vertices in the graph)
  313. whereas <code>EdgeIndex</code> could then be a 32-bit integer
  314. to allow a complete graph to be stored in the CSR format.<br>
  315. <b>Default</b>: <code>Vertex</code>
  316. </blockquote>
  317. <a name="properties"></a><h2>Interior Properties</h2>
  318. <p> The <tt>compressed_sparse_row_graph</tt> allows properties to
  319. be attached to its vertices, edges, or to the graph itself by way
  320. of its <a href="#template-parms">template parameters</a>. These
  321. properties may be accessed via
  322. the <a href="#property-access">member</a>
  323. and <a href="#property-map-accessors">non-member</a> property
  324. access functions, using the <a href="bundles.html">bundled
  325. properties</a> scheme.</p>
  326. <p>The CSR graph provides two kinds of built-in
  327. properties: <tt>vertex_index</tt>, which maps from vertices to
  328. values in <tt>[0, n)</tt> and <tt>edge_index</tt>, which maps
  329. from edges to values in <tt>[0, m)</tt>, where <tt>n</tt>
  330. and <tt>m</tt> are the number of vertices and edges in the graph,
  331. respectively. </p>
  332. <a name="member-functions"></a><h2>Member Functions</h2>
  333. <a name="constructors"></a><h3>Constructors</h3>
  334. <pre><a name="default-const"></a>
  335. compressed_sparse_row_graph();
  336. </pre>
  337. <p class="indent">Constructs a graph with no vertices or edges.</p>
  338. <hr></hr>
  339. <pre><a name="edge-const"></a>
  340. template&lt;typename InputIterator&gt;
  341. compressed_sparse_row_graph(edges_are_unsorted_t,
  342. InputIterator edge_begin, InputIterator edge_end,
  343. vertices_size_type numverts,
  344. const GraphProperty&amp; prop = GraphProperty());
  345. </pre>
  346. <p class="indent">
  347. Constructs a graph with <code>numverts</code> vertices whose
  348. edges are specified by the iterator range <code>[edge_begin,
  349. edge_end)</code>. The <tt>InputIterator</tt> must be a model of
  350. <a
  351. href="http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>
  352. whose <code>value_type</code> is an <code>std::pair</code> of
  353. integer values. These integer values are the source and target
  354. vertices for the edges, and must fall within the range <code>[0,
  355. numverts)</code>. The edges in <code>[edge_begin,
  356. edge_end)</code> do not need to be sorted. This constructor uses extra
  357. memory to save the edge information before adding it to the graph,
  358. avoiding the requirement for the iterator to have multi-pass capability.
  359. </p>
  360. <p class="indent">
  361. The value <code>prop</code> will be used to initialize the graph
  362. property.
  363. </p>
  364. <hr></hr>
  365. <pre><a name="edge-prop-const"></a>
  366. template&lt;typename InputIterator, typename EdgePropertyIterator&gt;
  367. compressed_sparse_row_graph(edges_are_unsorted_t,
  368. InputIterator edge_begin, InputIterator edge_end,
  369. EdgePropertyIterator ep_iter,
  370. vertices_size_type numverts,
  371. const GraphProperty&amp; prop = GraphProperty());
  372. </pre>
  373. <p class="indent">
  374. This constructor constructs a graph with <code>numverts</code>
  375. vertices and the edges provided in the iterator range
  376. <code>[edge_begin, edge_end)</code>. Its semantics are identical
  377. to the <a href="#edge-const">edge range constructor</a>, except
  378. that edge properties are also initialized. The type
  379. <tt>EdgePropertyIterator</tt> must be a model of the <a
  380. href="http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>
  381. concept whose <tt>value_type</tt> is convertible to
  382. <tt>EdgeProperty</tt>. The iterator range <tt>[ep_iter, ep_ter +
  383. m)</tt> will be used to initialize the properties on the edges
  384. of the graph, where <tt>m</tt> is distance from
  385. <tt>edge_begin</tt> to <tt>edge_end</tt>. This constructor uses extra
  386. memory to save the edge information before adding it to the graph,
  387. avoiding the requirement for the iterator to have multi-pass capability.
  388. </p>
  389. <hr></hr>
  390. <pre><a name="edge-multi-const"></a>
  391. template&lt;typename MultiPassInputIterator&gt;
  392. compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
  393. MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
  394. vertices_size_type numverts,
  395. const GraphProperty&amp; prop = GraphProperty());
  396. </pre>
  397. <p class="indent">
  398. Constructs a graph with <code>numverts</code> vertices whose
  399. edges are specified by the iterator range <code>[edge_begin,
  400. edge_end)</code>. The <tt>MultiPassInputIterator</tt> must be a model of
  401. <a
  402. href="../../utility/MultiPassInputIterator.html">MultiPassInputIterator</a>
  403. whose <code>value_type</code> is an <code>std::pair</code> of
  404. integer values. These integer values are the source and target
  405. vertices for the edges, and must fall within the range <code>[0,
  406. numverts)</code>. The edges in <code>[edge_begin,
  407. edge_end)</code> do not need to be sorted. Multiple passes will be made
  408. over the edge range.
  409. </p>
  410. <p class="indent">
  411. The value <code>prop</code> will be used to initialize the graph
  412. property.
  413. </p>
  414. <hr></hr>
  415. <pre><a name="edge-multi-prop-const"></a>
  416. template&lt;typename MultiPassInputIterator, typename EdgePropertyIterator&gt;
  417. compressed_sparse_row_graph(edges_are_unsorted_multi_pass_t,
  418. MultiPassInputIterator edge_begin, MultiPassInputIterator edge_end,
  419. EdgePropertyIterator ep_iter,
  420. vertices_size_type numverts,
  421. const GraphProperty&amp; prop = GraphProperty());
  422. </pre>
  423. <p class="indent">
  424. This constructor constructs a graph with <code>numverts</code>
  425. vertices and the edges provided in the iterator range
  426. <code>[edge_begin, edge_end)</code>. Its semantics are identical
  427. to the <a href="#edge-const">edge range constructor</a>, except
  428. that edge properties are also initialized. The type
  429. <tt>EdgePropertyIterator</tt> must be a model of the <a
  430. href="../../utility/MultiPassInputIterator.html">MultiPassInputIterator</a>
  431. concept whose <tt>value_type</tt> is convertible to
  432. <tt>EdgeProperty</tt>. The iterator range <tt>[ep_iter, ep_ter +
  433. m)</tt> will be used to initialize the properties on the edges
  434. of the graph, where <tt>m</tt> is distance from
  435. <tt>edge_begin</tt> to <tt>edge_end</tt>. Multiple passes will be made
  436. over the edge and property ranges.
  437. </p>
  438. <hr></hr>
  439. <pre><a name="edge-sorted-const"></a>
  440. template&lt;typename InputIterator&gt;
  441. compressed_sparse_row_graph(edges_are_sorted_t,
  442. InputIterator edge_begin, InputIterator edge_end,
  443. vertices_size_type numverts,
  444. edges_size_type numedges = 0,
  445. const GraphProperty&amp; prop = GraphProperty());
  446. </pre>
  447. <p class="indent">
  448. Constructs a graph with <code>numverts</code> vertices whose
  449. edges are specified by the iterator range <code>[edge_begin,
  450. edge_end)</code>. The argument of type <code>edges_are_sorted_t</code> is
  451. a tag used to distinguish this constructor; the value
  452. <code>edges_are_sorted</code> can be used to initialize this parameter.
  453. The <tt>InputIterator</tt> must be a model of
  454. <a
  455. href="http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>
  456. whose <code>value_type</code> is an <code>std::pair</code> of
  457. integer values. These integer values are the source and target
  458. vertices for the edges, and must fall within the range <code>[0,
  459. numverts)</code>. The edges in <code>[edge_begin,
  460. edge_end)</code> must be sorted so that all edges originating
  461. from vertex <i>i</i> precede any edges originating from all
  462. vertices <i>j</i> where <i>j &gt; i</i>.
  463. </p>
  464. <p class="indent">
  465. The value <code>numedges</code>, if provided, tells how many
  466. edges are in the range <code>[edge_begin, edge_end)</code> and
  467. will be used to preallocate data structures to save both memory
  468. and time during construction.
  469. </p>
  470. <p class="indent">
  471. The value <code>prop</code> will be used to initialize the graph
  472. property.
  473. </p>
  474. <hr></hr>
  475. <pre><a name="edge-sorted-prop-const"></a>
  476. template&lt;typename InputIterator, typename EdgePropertyIterator&gt;
  477. compressed_sparse_row_graph(edges_are_sorted_t,
  478. InputIterator edge_begin, InputIterator edge_end,
  479. EdgePropertyIterator ep_iter,
  480. vertices_size_type numverts,
  481. edges_size_type numedges = 0,
  482. const GraphProperty&amp; prop = GraphProperty());
  483. </pre>
  484. <p class="indent">
  485. This constructor constructs a graph with <code>numverts</code>
  486. vertices and the edges provided in the iterator range
  487. <code>[edge_begin, edge_end)</code>. Its semantics are identical
  488. to the <a href="#edge-const">edge range constructor</a>, except
  489. that edge properties are also initialized. The type
  490. <tt>EdgePropertyIterator</tt> must be a model of the <a
  491. href="http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>
  492. concept whose <tt>value_type</tt> is convertible to
  493. <tt>EdgeProperty</tt>. The iterator range <tt>[ep_iter, ep_ter +
  494. m)</tt> will be used to initialize the properties on the edges
  495. of the graph, where <tt>m</tt> is distance from
  496. <tt>edge_begin</tt> to <tt>edge_end</tt>.
  497. </p>
  498. <hr></hr>
  499. <pre><a name="edge-inplace-const"></a>
  500. template&lt;typename InputIterator&gt;
  501. compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,
  502. std::vector&lt;vertex_descriptor&gt;&amp; sources,
  503. std::vector&lt;vertex_descriptor&gt;&amp; targets,
  504. vertices_size_type numverts,
  505. const GraphProperty&amp; prop = GraphProperty());
  506. </pre>
  507. <p class="indent">
  508. This constructor constructs a graph with <code>numverts</code> vertices
  509. and the edges provided in the two vectors <code>sources</code> and
  510. <code>targets</code>. The two vectors are mutated in-place to sort them
  511. by source vertex. They are returned with unspecified values, but do not
  512. share storage with the constructed graph (and so are safe to destroy).
  513. The parameter <code>prop</code>, if provided, is used to initialize the
  514. graph property.
  515. </p>
  516. <hr></hr>
  517. <pre><a name="edge-inplace-prop-const"></a>
  518. template&lt;typename InputIterator&gt;
  519. compressed_sparse_row_graph(construct_inplace_from_sources_and_targets_t,
  520. std::vector&lt;vertex_descriptor&gt;&amp; sources,
  521. std::vector&lt;vertex_descriptor&gt;&amp; targets,
  522. std::vector&lt;EdgeProperty&gt;&amp; edge_props,
  523. vertices_size_type numverts,
  524. const GraphProperty&amp; prop = GraphProperty());
  525. </pre>
  526. <p class="indent">
  527. This constructor constructs a graph with <code>numverts</code> vertices
  528. and the edges provided in the two vectors <code>sources</code> and
  529. <code>targets</code>. Edge properties are initialized from the vector
  530. <code>edge_props</code>. The three vectors are mutated in-place to sort
  531. them by source vertex. They are returned with unspecified values, but do
  532. not share storage with the constructed graph (and so are safe to
  533. destroy). The parameter <code>prop</code>, if provided, is used to
  534. initialize the graph property.
  535. </p>
  536. <hr></hr>
  537. <pre><a name="graph-const"></a>
  538. template&lt;typename Graph, typename VertexIndexMap&gt;
  539. compressed_sparse_row_graph(const Graph&amp; g, const VertexIndexMap&amp; vi,
  540. vertices_size_type numverts,
  541. edges_size_type numedges);
  542. template&lt;typename Graph, typename VertexIndexMap&gt;
  543. compressed_sparse_row_graph(const Graph&amp; g, const VertexIndexMap&amp; vi);
  544. template&lt;typename Graph&gt;
  545. explicit compressed_sparse_row_graph(const Graph&amp; g);
  546. </pre>
  547. <p class="indent">
  548. Calls the <a href="#assign"><tt>assign</tt></a> function with
  549. all of the arguments it is given.
  550. </p>
  551. <hr></hr>
  552. <a name="mutators"></a><h3>Mutators</h3>
  553. <pre><a name="assign"></a>
  554. template&lt;typename Graph, typename VertexIndexMap&gt;
  555. void assign(const Graph&amp; g, const VertexIndexMap&amp; vi,
  556. vertices_size_type numverts, edges_size_type numedges);
  557. template&lt;typename Graph, typename VertexIndexMap&gt;
  558. void assign(const Graph&amp; g, const VertexIndexMap&amp; vi);
  559. template&lt;typename Graph&gt;
  560. void assign(const Graph&amp; g);
  561. </pre>
  562. <p class="indent">
  563. Clears the CSR graph and builds a CSR graph in place from the
  564. structure of another graph. The graph type <tt>Graph</tt> must
  565. be a model of <a href="IncidenceGraph.html">IncidenceGraph</a>.
  566. <br><b>Parameters</b>
  567. <ul>
  568. <li><tt>g</tt>: The incoming graph.</li>
  569. <li><tt>vi</tt>: A map from vertices to indices. If not
  570. provided, <tt>get(vertex_index, g)</tt> will be used.</li>
  571. <li><tt>numverts</tt>: The number of vertices in the graph
  572. <tt>g</tt>. If not provided, <tt>Graph</tt> must be a model of
  573. <a href="VertexListGraph.html">VertexListGraph</a>.</li>
  574. <li><tt>numedges</tt>: The number of edges in the graph
  575. <tt>g</tt>. If not provided, <tt>Graph</tt> must be a model of
  576. <a href="EdgeListGraph.html">EdgeListGraph</a>.</li>
  577. </ul>
  578. </p>
  579. <hr></hr>
  580. <a name="property-access"></a><h3>Property Access</h3>
  581. <pre><a name="vertex-subscript"></a>
  582. VertexProperty&amp; operator[](vertex_descriptor v);
  583. const VertexProperty&amp; operator[](vertex_descriptor v) const;
  584. </pre>
  585. <p class="indent">
  586. Retrieves the property value associated with vertex
  587. <tt>v</tt>. Only valid when <tt>VertexProperty</tt> is a class
  588. type that is not <tt>no_property</tt>.
  589. </p>
  590. <hr></hr>
  591. <pre><a name="edge-subscript">
  592. EdgeProperty&amp; operator[](edge_descriptor v);
  593. const EdgeProperty&amp; operator[](edge_descriptor v) const;
  594. </pre>
  595. <p class="indent">
  596. Retrieves the property value associated with edge
  597. <tt>v</tt>. Only valid when <tt>EdgeProperty</tt> is a class
  598. type that is not <tt>no_property</tt>.
  599. </p>
  600. <hr></hr>
  601. <a name="non-members"></a><h2>Non-member Functions</h2>
  602. <a name="vertex-access"></a><h3>Vertex access</h3>
  603. <pre><a name="vertex-lookup"></a>
  604. vertex_descriptor vertex(vertices_size_type i, const compressed_sparse_row_graph&amp;);
  605. </pre>
  606. <p class="indent">
  607. Retrieves the <i>i</i><sup>th</sup> vertex in the graph in
  608. constant time.
  609. </p>
  610. <hr></hr>
  611. <a name="edge-access"></a><h3>Edge access</h3>
  612. <pre><a name="edge"></a>
  613. std::pair&lt;edge_descriptor, bool&gt;
  614. edge(vertex_descriptor u, vertex_descriptor v, const compressed_sparse_row_graph&amp;);
  615. </pre>
  616. <p class="indent">
  617. If there exists an edge <i>(u, v)</i> in the graph, returns the
  618. descriptor for that edge and <tt>true</tt>; otherwise, the
  619. second value in the pair will be <tt>false</tt>. If multiple
  620. edges exist from <tt>u</tt> to <tt>v</tt>, the first edge will
  621. be returned; use <a href="IncidenceGraph.html"><tt>out_edges</tt></a> and a
  622. conditional statement
  623. to retrieve all edges to a given target. This function requires linear
  624. time in the
  625. number of edges outgoing from <tt>u</tt>.
  626. </p>
  627. <hr></hr>
  628. <pre><a name="edge_from_index"></a>
  629. edge_descriptor edge_from_index(edges_size_type i, const compressed_sparse_row_graph&amp;);
  630. </pre>
  631. <p class="indent">
  632. Returns the <i>i</i><sup>th</sup> edge in the graph. This
  633. operation requires logarithmic time in the number of vertices.
  634. </p>
  635. <hr></hr>
  636. <h3><a name="property-map-accessors">Property Map Accessors</a></h3>
  637. <pre><a name="get"></a>
  638. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>&gt;
  639. property_map&lt;compressed_sparse_row_graph, PropertyTag&gt;::type
  640. get(PropertyTag, compressed_sparse_row_graph&amp; g)
  641. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>&gt;
  642. property_map&lt;compressed_sparse_row_graph, Tag&gt;::const_type
  643. get(PropertyTag, const compressed_sparse_row_graph&amp; g)
  644. </pre>
  645. <p class="indent">
  646. Returns the property map object for the vertex property
  647. specified by <TT>PropertyTag</TT>. The <TT>PropertyTag</TT> must
  648. be a member pointer to access one of the fields in
  649. <tt>VertexProperty</tt> or <tt>EdgeProperty</tt>.
  650. </p>
  651. <hr></hr>
  652. <pre><a name="get-x"></a>
  653. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>, class X&gt;
  654. typename property_traits&lt;property_map&lt;compressed_sparse_row_graph, PropertyTag&gt;::const_type&gt::value_type
  655. get(PropertyTag, const compressed_sparse_row_graph&amp; g, X x)
  656. </pre>
  657. <p class="indent">
  658. This returns the property value for <tt>x</tt>, where <tt>x</tt>
  659. is either a vertex or edge descriptor.
  660. </p>
  661. <hr></hr>
  662. <pre><a name="put-x"></a>
  663. template&lt;typename <a href="./PropertyTag.html">PropertyTag</a>, class X, class Value&gt;
  664. void put(PropertyTag, const compressed_sparse_row_graph&amp; g, X x, const Value&amp; value);
  665. </pre>
  666. <p class="indent">
  667. This sets the property value for <tt>x</tt> to
  668. <tt>value</tt>. <tt>x</tt> is either a vertex or edge
  669. descriptor. <tt>Value</tt> must be convertible to <tt>typename
  670. property_traits&lt;property_map&lt;compressed_sparse_row_graph,
  671. PropertyTag&gt;::type&gt::value_type</tt>
  672. </p>
  673. <hr></hr>
  674. <pre><a name="get_property"></a>
  675. template&lt;typename <a href="./PropertyTag.html#GraphPropertyTag">GraphPropertyTag</a>&gt;
  676. typename graph_property&lt;compressed_sparse_row_graph, GraphPropertyTag&gt;::type&amp;
  677. get_property(compressed_sparse_row_graph&amp; g, GraphPropertyTag);
  678. template&lt;typename <a href="./PropertyTag.html#GraphPropertyTag">GraphPropertyTag</a>&gt;
  679. typename graph_property&lt;compressed_sparse_row_graph, GraphPropertyTag&gt;::type const &amp;
  680. get_property(const compressed_sparse_row_graph&amp; g, GraphPropertyTag);
  681. </pre>
  682. <p class="indent">
  683. Return the property specified by <tt>GraphPropertyTag</tt> that
  684. is attached to the graph object <tt>g</tt>.
  685. </p>
  686. <hr></hr>
  687. <pre><a name="set_property"></a>
  688. template&lt;typename <a href="./PropertyTag.html#GraphPropertyTag">GraphPropertyTag</a>&gt;
  689. void set_property(const compressed_sparse_row_graph&amp; g, GraphPropertyTag,
  690. const typename graph_property&lt;compressed_sparse_row_graph, GraphPropertyTag&gt;::type&amp; value);
  691. </pre>
  692. <p class="indent">
  693. Set the property specified by <tt>GraphPropertyTag</tt> that
  694. is attached to the graph object <tt>g</tt>.
  695. </p>
  696. <hr></hr>
  697. <h3><a name="incremental-construction-functions">Incremental construction functions</a></h3>
  698. <pre><a name="add_edges"></a>
  699. template&lt;typename InputIterator&gt;
  700. void add_edges(InputIterator first, InputIterator last, compressed_sparse_row_graph&amp; g)
  701. </pre>
  702. <p class="indent">
  703. Add a range of edges (from <tt>first</tt> to <tt>last</tt>) to the graph.
  704. The <tt>InputIterator</tt> must be a model of <a
  705. href="http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>
  706. whose <code>value_type</code> is an <code>std::pair</code> of integer
  707. values. These integer values are the source and target vertices of the
  708. new edges. The edges do not need to be sorted.
  709. </p>
  710. <hr></hr>
  711. <pre><a name="add_edges_prop"></a>
  712. template&lt;typename InputIterator, typename EPIter&gt;
  713. void add_edges(InputIterator first, InputIterator last, EPIter ep_first, EPIter ep_last, compressed_sparse_row_graph&amp; g)
  714. </pre>
  715. <p class="indent">
  716. Add a range of edges (from <tt>first</tt> to <tt>last</tt>) with
  717. corresponding edge properties (from <tt>ep_first</tt> to
  718. <tt>ep_last</tt>) to the graph. The <tt>InputIterator</tt> and
  719. <tt>EPIter</tt> must be models of <a
  720. href="http://www.boost.org/sgi/stl/InputIterator.html">InputIterator</a>;
  721. the <code>value_type</code> of <tt>InputIterator</tt> must be an
  722. <code>std::pair</code> of integer values, and the <code>value_type</code>
  723. of <tt>EPIter</tt> must be the edge property type of the graph. The
  724. integer values produced by the <tt>InputIterator</tt> are the source and
  725. target vertices of the new edges. The edges do not need to be sorted.
  726. </p>
  727. <hr></hr>
  728. <pre><a name="add_edges_sorted"></a>
  729. template&lt;typename BidirectionalIterator&gt;
  730. void add_edges_sorted(BidirectionalIterator first, BidirectionalIterator last, compressed_sparse_row_graph&amp; g)
  731. </pre>
  732. <p class="indent">
  733. Add a range of edges (from <tt>first</tt> to <tt>last</tt>) to the graph.
  734. The <tt>BidirectionalIterator</tt> must be a model of <a
  735. href="http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>
  736. whose <code>value_type</code> is an <code>std::pair</code> of integer
  737. values. These integer values are the source and target vertices of the
  738. new edges. The edges must be sorted in increasing order by source vertex
  739. index.
  740. </p>
  741. <hr></hr>
  742. <pre><a name="add_edges_sorted_prop"></a>
  743. template&lt;typename BidirectionalIterator, typename EPIter&gt;
  744. void add_edges_sorted(BidirectionalIterator first, BidirectionalIterator last, EPIter ep_iter, compressed_sparse_row_graph&amp; g)
  745. </pre>
  746. <p class="indent">
  747. Add a range of edges (from <tt>first</tt> to <tt>last</tt>) to the graph.
  748. The <tt>BidirectionalIterator</tt> and <tt>EPIter</tt> must be models of
  749. <a
  750. href="http://www.boost.org/sgi/stl/BidirectionalIterator.html">BidirectionalIterator</a>.
  751. The <code>value_type</code> of the <tt>BidirectionalIterator</tt> must be
  752. an <code>std::pair</code> of integer
  753. values. These integer values are the source and target vertices of the
  754. new edges.
  755. The <code>value_type</code> of the <tt>EPIter</tt> must be the edge
  756. property type of the graph.
  757. The edges must be sorted in increasing order by source vertex
  758. index.
  759. </p>
  760. <hr></hr>
  761. <a name="example"></a><h2>Example</h2>
  762. <br>[<a
  763. href="../example/csr-example.cpp">libs/graph/example/csr-example.cpp</a>]
  764. <p>We will use the <tt>compressed_sparse_row_graph</tt> graph
  765. class to store a simple Web graph. In this web graph the vertices
  766. represent web pages and the edges represent links from one web
  767. page to another. With each web page we want to associate a URL, so
  768. we initially create a <tt>WebPage</tt> class that stores the
  769. URL. Then we can create our graph type by providing
  770. <tt>WebPage</tt> as a parameter to the
  771. <tt>compressed_sparse_row_graph</tt> class template.</p>
  772. <pre>
  773. class WebPage
  774. {
  775. public:
  776. std::string url;
  777. };
  778. // ...
  779. typedef compressed_sparse_row_graph&lt;directedS, WebPage&gt; WebGraph;
  780. WebGraph g(&the_edges[0], &the_edges[0] + sizeof(the_edges)/sizeof(E), 6);
  781. </pre>
  782. <p>We can then set the properties on the vertices of the graph
  783. using the <a href="bundles.html">bundled properties</a> syntax,
  784. and display the edges for the user.</p>
  785. <pre>
  786. // Set the URLs of each vertex
  787. int index = 0;
  788. BGL_FORALL_VERTICES(v, g, WebGraph)
  789. g[v].url = urls[index++];
  790. // Output each of the links
  791. std::cout &lt;&lt; "The web graph:" &lt;&lt; std::endl;
  792. BGL_FORALL_EDGES(e, g, WebGraph)
  793. std::cout &lt;&lt; " " &lt;&lt; g[source(e, g)].url &lt;&lt; " -> " &lt;&lt; g[target(e, g)].url
  794. &lt;&lt; std::endl;
  795. </pre>
  796. <p>See the <a href="../example/csr-example.cpp">complete example
  797. source</a> for other operations one can perform with a
  798. <tt>compressed_sparse_row_graph</tt>.</p>
  799. <br>
  800. <HR>
  801. <TABLE>
  802. <TR valign=top>
  803. <TD nowrap>Copyright &copy; 2005</TD><TD>
  804. <A HREF="http://www.boost.org/people/doug_gregor.html">Doug Gregor</A>, Indiana University (<script language="Javascript">address("cs.indiana.edu", "dgregor")</script>)<br>
  805. Jeremiah Willcock, Indiana University (<script language="Javascript">address("osl.iu.edu", "jewillco")</script>)<br>
  806. <A HREF="https://homes.cs.washington.edu/~al75">Andrew Lumsdaine</A>,
  807. Indiana University (<script language="Javascript">address("osl.iu.edu", "lums")</script>)
  808. </TD></TR></TABLE>
  809. </body>
  810. </html>