• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1<HTML>
2<!--
3     Copyright (c) Jeremy Siek 2001
4
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>Boost Graph Library: Transitive Closure</Title>
11<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
12        ALINK="#ff0000">
13<IMG SRC="../../../boost.png"
14     ALT="C++ Boost" width="277" height="86">
15
16<BR Clear>
17
18<H1><A NAME="sec:transitive_closure">
19<img src="figs/python.gif" alt="(Python)"/>
20<TT>transitive_closure</TT>
21</H1>
22
23<P>
24<PRE>
25template &lt;typename Graph, typename GraphTC,
26  typename P, typename T, typename R&gt;
27void transitive_closure(const Graph&amp; g, GraphTC&amp; tc,
28  const bgl_named_params&lt;P, T, R&gt;&amp; params = <i>all defaults</i>)
29
30template &lt;typename Graph, typename GraphTC,
31  typename G_to_TC_VertexMap, typename VertexIndexMap&gt;
32void transitive_closure(const Graph&amp; g, GraphTC&amp; tc,
33                        G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map)
34</PRE>
35
36The transitive closure of a graph <i>G = (V,E)</i> is a graph <i>G* =
37(V,E*)</i> such that <i>E*</i> contains an edge <i>(u,v)</i> if and
38only if <i>G</i> contains a <a
39href="graph_theory_review.html#def:path">path</a> (of at least one
40edge) from <i>u</i> to <i>v</i>. The <tt>transitive_closure()</tt>
41function transforms the input graph <tt>g</tt> into the transitive
42closure graph <tt>tc</tt>.
43
44<p>
45Thanks to Vladimir Prus for the implementation of this algorithm!
46
47
48
49<H3>Where Defined</H3>
50
51<P>
52<a href="../../../boost/graph/transitive_closure.hpp"><TT>boost/graph/transitive_closure.hpp</TT></a>
53
54<h3>Parameters</h3>
55
56IN: <tt>const Graph&amp; g</tt>
57<blockquote>
58 A directed graph, where the <tt>Graph</tt> type must model the
59 <a href="./VertexListGraph.html">Vertex List Graph</a>,
60 <a href="./AdjacencyGraph.html">Adjacency Graph</a>,
61 and <a href="./AdjacencyMatrix.html">Adjacency Matrix</a> concepts.<br>
62
63  <b>Python</b>: The parameter is named <tt>graph</tt>.
64</blockquote>
65
66OUT: <tt>GraphTC&amp; tc</tt>
67<blockquote>
68 A directed graph, where the <tt>GraphTC</tt> type must model the
69 <a href="./VertexMutableGraph.html">Vertex Mutable Graph</a>
70 and <a href="./EdgeMutableGraph.html">Edge Mutable Graph</a> concepts.<br>
71
72 <b>Python</b>: This parameter is not used in Python. Instead, a new
73 graph of the same type is returned.
74</blockquote>
75
76<h3>Named Parameters</h3>
77
78UTIL/OUT: <tt>orig_to_copy(G_to_TC_VertexMap g_to_tc_map)</tt>
79<blockquote>
80  This maps each vertex in the input graph to the new matching
81  vertices in the output transitive closure graph.<br>
82
83  <b>Python</b>: This must be a <tt>vertex_vertex_map</tt> of the graph.
84</blockquote>
85
86IN: <tt>vertex_index_map(VertexIndexMap&amp; index_map)</tt>
87<blockquote>
88  This maps each vertex to an integer in the range <tt>[0,
89  num_vertices(g))</tt>. This parameter is only necessary when the
90  default color property map is used. The type <tt>VertexIndexMap</tt>
91  must be a model of <a
92  href="../../property_map/doc/ReadablePropertyMap.html">Readable Property
93  Map</a>. The value type of the map must be an integer type. The
94  vertex descriptor type of the graph needs to be usable as the key
95  type of the map.<br>
96
97  <b>Default:</b> <tt>get(vertex_index, g)</tt>
98    Note: if you use this default, make sure your graph has
99    an internal <tt>vertex_index</tt> property. For example,
100    <tt>adjacency_list</tt> with <tt>VertexList=listS</tt> does
101    not have an internal <tt>vertex_index</tt> property.
102   <br>
103
104  <b>Python</b>: Unsupported parameter.
105</blockquote>
106
107
108<h3>Complexity</h3>
109
110The time complexity (worst-case) is <i>O(|V||E|)</i>.
111
112<h3>Example</h3>
113
114The following is the graph from the example <tt><a
115href="../example/transitive_closure.cpp">example/transitive_closure.cpp</a></tt>
116and the transitive closure computed by the algorithm.
117
118<table>
119  <tr>
120    <td><img src="tc.gif" width="173" height="264" ></td>
121    <td><img src="tc-out.gif" width="200" height="360"></td>
122  </tr>
123</table>
124
125
126<h3>Implementation Notes</h3>
127
128<p>
129The algorithm used to implement the <tt>transitive_closure()</tt>
130function is based on the detection of strong components[<a
131href="bibliography.html#nuutila95">50</a>, <a
132href="bibliography.html#purdom70">53</a>]. The following discussion
133describes the algorithm (and some relevant background theory).
134
135<p>
136A <a name="def:successor-set"><i><b>successor set</b></i></a> of a
137vertex <i>v</i>, denoted by <i>Succ(v)</i>, is the set of vertices
138that are <a
139href="graph_theory_review.html#def:reachable">reachable</a> from
140vertex <i>v</i>. The set of vertices adjacent to <i>v</i> in the
141transitive closure <i>G*</i> is the same as the successor set of
142<i>v</i> in the original graph <i>G</i>. Computing the transitive
143closure is equivalent to computing the successor set for every vertex
144in <i>G</i>.
145
146<p>
147All vertices in the same strong component have the same successor set
148(because every vertex is reachable from all the other vertices in the
149component). Therefore, it is redundant to compute the successor set
150for every vertex in a strong component; it suffices to compute it for
151just one vertex per component.
152
153<p>
154The following is the outline of the algorithm:
155
156<ol>
157<li>Compute <a
158href="strong_components.html#def:strongly-connected-component">strongly
159connected components</a> of the graph.
160
161<li> Construct the condensation graph.  A <a
162name="def:condensation-graph"><i><b>condensation graph</b></i></a> is
163a a graph <i>G'=(V',E')</i> based on the graph <i>G=(V,E)</i> where
164each vertex in <i>V'</i> corresponds to a strongly connected component
165in <i>G</i> and edge <i>(u,v)</i> is in <i>E'</i> if and only if there
166exists an edge in <i>E</i> connecting any of the vertices in the
167component of <i>u</i> to any of the vertices in the component of
168<i>v</i>.
169
170<li> Compute transitive closure on the condensation graph.
171  This is done using the following algorithm:
172<pre>
173 for each vertex u in G' in reverse topological order
174   for each vertex v in Adj[u]
175     if (v not in Succ(u))
176       Succ(u) = Succ(u) U { v } U Succ(v)   // &quot;U&quot; means set union
177</pre>
178  The vertices are considered in reverse topological order to
179  ensure that the when computing the successor set for a vertex
180  <i>u</i>, the successor set for each vertex in <i>Adj[u]</i>
181  has already been computed.
182
183  <p>An optimized implementation of the set union operation improves
184   the performance of the algorithm. Therefore this implementation
185   uses <a name="def:chain-decomposition"><i><b>chain
186   decomposition</b></i></a> [<a
187   href="bibliography.html#goral79">51</a>,<a
188   href="bibliography.html#simon86">52</a>]. The vertices of <i>G</i>
189   are partitioned into chains <i>Z<sub>1</sub>, ...,
190   Z<sub>k</sub></i>, where each chain <i>Z<sub>i</sub></i> is a path
191   in <i>G</i> and the vertices in a chain have increasing topological
192   number.  A successor set <i>S</i> is then represented by a
193   collection of intersections with the chains, i.e., <i>S =
194   U<sub>i=1...k</sub> (Z<sub>i</sub> &amp; S)</i>. Each intersection
195   can be represented by the first vertex in the path
196   <i>Z<sub>i</sub></i> that is also in <i>S</I>, since the rest of
197   the path is guaranteed to also be in <i>S</i>. The collection of
198   intersections is therefore represented by a vector of length
199   <i>k</i> where the ith element of the vector stores the first
200   vertex in the intersection of <i>S</i> with <i>Z<sub>i</sub></i>.
201
202   <p>Computing the union of two successor sets, <i>S<sub>3</sub> =
203   S<sub>1</sub> U S<sub>2</sub></i>, can then be computed in
204   <i>O(k)</i> time with the following operation:
205<pre>
206  for i = 0...k
207    S3[i] = min(S1[i], S2[i]) // where min compares the topological number of the vertices
208</pre>
209
210<li>Create the graph <i>G*</i> based on the transitive closure of
211 the condensation graph <i>G'*</i>.
212
213</ol>
214
215<br>
216<HR>
217<TABLE>
218<TR valign=top>
219<TD nowrap>Copyright &copy; 2001</TD><TD>
220<A HREF="http://www.boost.org/people/jeremy_siek.htm">Jeremy Siek</A>, Indiana Univ.(<A HREF="mailto:jsiek@cs.indiana.edu">jsiek@cs.indiana.edu</A>)
221</TD></TR></TABLE>
222
223</BODY>
224</HTML>
225