Merge from graph_devel_1_33_0 branch

[SVN r25893]
This commit is contained in:
Douglas Gregor 2004-10-27 14:38:15 +00:00
parent 63cfb2e00b
commit 71b302bc49
26 changed files with 3684 additions and 14 deletions

142
doc/AStarHeuristic.html Normal file
View File

@ -0,0 +1,142 @@
<HTML>
<!--
-- Copyright (c) 2004 Kris Beevers
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: AStarHeuristic</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1>AStar Heuristic Concept</H1>
This concept defines the interface for the heuristic function of an A*
search, which is responsible for estimating the remaining cost from
some vertex to a goal. The user can create a class that matches this
interface, and then pass objects of the class into <a
href="./astar_search.html"><tt>astar_search()</tt></a> to guide the
order of vertex examination of the search. The heuristic instance
must incorporate any necessary information about goal vertices in the
graph.
For further discussion of the use of heuristics in an A* search, see
the documentation of <a
href="./astar_search.html">astar_search()</a>.
<h3>Refinement of</h3>
<a href="http://www.sgi.com/tech/stl/UnaryFunction.html">Unary
Function</a> (must take a single argument -- a graph vertex -- and
return a cost value) and <a
href="../../utility/CopyConstructible.html">Copy Constructible</a>
(copying a heuristic should be a lightweight operation).
<h3>Notation</h3>
<Table>
<TR>
<TD><tt>H</tt></TD>
<TD>A type that is a model of AStar Heuristic.</TD>
</TR>
<TR>
<TD><tt>h</tt></TD>
<TD>An object of type <tt>H</tt>.</TD>
</TR>
<TR>
<TD><tt>G</tt></TD>
<TD>A type that is a model of Graph.</TD>
</TR>
<TR>
<TD><tt>g</tt></TD>
<TD>An object of type <tt>G</tt>.</TD>
</TR>
<TR>
<TD><tt>u</tt></TD>
<TD>An object of type <tt>boost::graph_traits&lt;G&gt;::vertex_descriptor</tt>.</TD>
</TR>
<TR>
<TD><tt>CostType</tt></TD>
<TD>A type that can be used with the <tt>compare</tt> and
<tt>combine</tt> functions passed to A*.</TD>
</TR>
<TR>
<TD><tt>c</tt></TD>
<TD>An object of type <tt>CostType</tt>.</TD>
</TR>
</table>
<h3>Associated Types</h3>
none
<p>
<h3>Valid Expressions</h3>
<table border>
<tr>
<th>Name</th><th>Expression</th><th>Return Type</th><th>Description</th>
</tr>
<tr>
<td>Call Heuristic</td>
<td><tt>CostType c = h(u)</tt></td>
<td><tt>CostType</tt></td>
<td>
Called for the target of every out edge of a vertex being examined.
</td>
</tr>
</table>
<h3>Models</h3>
<ul>
<li><a href="./astar_heuristic.html"><tt>astar_heuristic</tt></a>
</ul>
<h3>Concept Checking Class</h3>
<pre>
template &lt;class Heuristic, class Graph&gt;
struct AStarHeuristicConcept {
void constraints()
{
function_requires&lt; CopyConstructibleConcept&lt;Heuristic&gt; &gt;();
h(u);
}
Heuristic h;
typename graph_traits&lt;Graph&gt;::vertex_descriptor u;
};
</pre>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2004</TD><TD>
<A HREF="http://www.cs.rpi.edu/~beevek/">Kristopher Beevers</A>,
Rensselaer Polytechnic Institute (<A
HREF="mailto:beevek@cs.rpi.edu">beevek@cs.rpi.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

217
doc/AStarVisitor.html Normal file
View File

@ -0,0 +1,217 @@
<HTML>
<!--
-- Copyright (c) 2004 Kris Beevers
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: AStarVisitor</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1>AStar Visitor Concept</H1>
This concept defines the visitor interface for <a
href="./astar_search.html"><tt>astar_search()</tt></a>. Users can
define a class with the AStar Visitor interface and pass an object of
the class to <tt>astar_search()</tt>, thereby augmenting the actions
taken during the graph search.
<h3>Refinement of</h3>
<a href="../../utility/CopyConstructible.html">Copy Constructible</a>
(copying a visitor should be a lightweight operation).
<h3>Notation</h3>
<Table>
<TR>
<TD><tt>V</tt></TD>
<TD>A type that is a model of AStar Visitor.</TD>
</TR>
<TR>
<TD><tt>vis</tt></TD>
<TD>An object of type <tt>V</tt>.</TD>
</TR>
<TR>
<TD><tt>G</tt></TD>
<TD>A type that is a model of Graph.</TD>
</TR>
<TR>
<TD><tt>g</tt></TD>
<TD>An object of type <tt>G</tt>.</TD>
</TR>
<TR>
<TD><tt>e</tt></TD>
<TD>An object of type <tt>boost::graph_traits&lt;G&gt;::edge_descriptor</tt>.</TD>
</TR>
<TR>
<TD><tt>s,u,v</tt></TD>
<TD>An object of type <tt>boost::graph_traits&lt;G&gt;::vertex_descriptor</tt>.</TD>
</TR>
<TR>
<TD><tt>d</tt></TD>
<TD>An object of type <tt>DistanceMap</tt>.</TD>
</TR>
<TR>
<TD><tt>WeightMap</tt></TD>
<TD>A type that is a model of <a
href="../../property_map/ReadablePropertyMap.html">Readable Property
Map</a>.</TD>
</TR>
<TR>
<TD><tt>w</tt></TD>
<TD>An object of type <tt>WeightMap</tt>.</TD>
</TR>
</table>
<h3>Associated Types</h3>
none
<p>
<h3>Valid Expressions</h3>
<table border>
<tr>
<th>Name</th><th>Expression</th><th>Return Type</th><th>Description</th>
</tr>
<tr>
<td>Initialize Vertex</td>
<td><tt>vis.initialize_vertex(u, g)</tt></td>
<td><tt>void</tt></td>
<td>
This is invoked on each vertex of the graph when it is first
initialized (i.e., when its property maps are initialized).
</td>
</tr>
<tr>
<td>Discover Vertex</td>
<td><tt>vis.discover_vertex(u, g)</tt></td>
<td><tt>void</tt></td>
<td>
This is invoked when a vertex is first discovered and is added to the
OPEN list.
</td>
</tr>
<tr>
<td>Examine Vertex</td>
<td><tt>vis.examine_vertex(u, g)</tt></td>
<td><tt>void</tt></td>
<td>
This is invoked on a vertex as it is popped from the queue (i.e. it
has the lowest cost on the OPEN list). This happens immediately before
<tt>examine_edge()</tt> is invoked on each of the out-edges of vertex
<tt>u</tt>.
</td>
</tr>
<tr>
<td>Examine Edge</td>
<td><tt>vis.examine_edge(e, g)</tt></td>
<td><tt>void</tt></td>
<td>
This is invoked on every out-edge of each vertex after it is
examined.
</td>
</tr>
<tr>
<td>Edge Relaxed</td>
<td><tt>vis.edge_relaxed(e, g)</tt></td>
<td><tt>void</tt></td>
<td>
Upon examination, if the following condition holds then the edge is
relaxed (the distance of its target vertex is reduced) and this method
is invoked:
<blockquote>
<pre>
tie(u, s) = incident(e, g);
D d_u = get(d, u), d_v = get(d, s);
W w_e = get(w, e);
assert(compare(combine(d_u, w_e), d_s));
</pre>
</blockquote>
</td>
</tr>
<tr>
<td>Edge Not Relaxed</td>
<td><tt>vis.edge_not_relaxed(e, g)</tt></td>
<td><tt>void</tt></td>
<td>
Upon examination, if an edge is not relaxed (see above), then this
method is invoked.
</td>
</tr>
<tr>
<td>Black Target</td>
<td><tt>vis.black_target(e, g)</tt></td>
<td><tt>void</tt></td>
<td>
This is invoked when a vertex that is on the CLOSED list is
``rediscovered'' via a more efficient path, and is re-added to the
OPEN list.
</td>
</tr>
<tr>
<td>Finish Vertex</td>
<td><tt>vis.finish_vertex(u, g)</tt></td>
<td><tt>void</tt></td>
<td>
This is invoked on a vertex when it is added to the CLOSED list, which
happens after all of its out edges have been examined.
</td>
</tr>
</table>
<h3>Models</h3>
<ul>
<li><a href="./astar_visitor.html"><tt>astar_visitor</tt></a>
</ul>
<h3>See also</h3>
<a href="./visitor_concepts.html">Visitor concepts</a>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2004</TD><TD>
<A HREF="http://www.cs.rpi.edu/~beevek/">Kristopher Beevers</A>,
Rensselaer Polytechnic Institute (<A
HREF="mailto:beevek@cs.rpi.edu">beevek@cs.rpi.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

100
doc/astar_heuristic.html Normal file
View File

@ -0,0 +1,100 @@
<HTML>
<!--
-- Copyright (c) 2004 Kris Beevers
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: astar_heuristic</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1>
<pre>
astar_heuristic&lt;Graph, CostType&gt;
</pre>
</H1>
This class is a default implementation of the <a
href="./AStarHeuristic.html">AStarHeuristic</a> concept. It
implements a "zero" heuristic -- a heuristic function that returns a
cost of zero regardless of the vertex it is passed.
<h3>Model of</h3>
<a href="./AStarHeuristic.html">AStarHeuristic</a>
<H3>Template Parameters</H3>
<P>
<TABLE border>
<TR>
<th>Parameter</th><th>Description</th><th>Default</th>
</tr>
<TR><TD><TT>Graph</TT></TD>
<TD>
The type of the graph being searched.
</TD>
<TD></TD>
</TR>
<TR><TD><TT>CostType</TT></TD>
<TD>
A type that can be used with the <tt>compare</tt> and
<tt>combine</tt> functions passed to A*. Typically an integer or
floating point type.
</TD>
<TD></TD>
</TR>
</table>
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/astar_search.hpp">
<TT>boost/graph/astar_search.hpp</TT></a>
<h3>Member Functions</h3>
This class implements the single member function required by <a
href="./AStarHeuristic.html">AStarHeuristic</a>:
<table border>
<tr>
<th>Function</th><th>Description</th>
</tr>
<tr><td><tt>
CostType operator()(graph_traits&lt;Graph&gt;::vertex_descriptor u);
</tt></td><td>
Called for the target of every out edge of a vertex being examined.
Returns the cost, estimated by the heuristic, from vertex <tt>u</tt>
to a goal.
</td></tr>
</table>
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2004</TD><TD>
<A HREF="http://www.cs.rpi.edu/~beevek/">Kristopher Beevers</A>,
Rensselaer Polytechnic Institute (<A
HREF="mailto:beevek@cs.rpi.edu">beevek@cs.rpi.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

477
doc/astar_search.html Normal file
View File

@ -0,0 +1,477 @@
<HTML>
<!--
-- Copyright (c) 2004 Kris Beevers
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: A* Heuristic Search</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../boost.png"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1><A NAME="sec:astar"></A>
<TT>astar_search</TT>
</H1>
<P>
<PRE>
<i>// Named parameter interface</i>
template &lt;typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R&gt;
void
astar_search
(VertexListGraph &amp;g,
typename graph_traits&lt;VertexListGraph&gt;::vertex_descriptor s,
<a href="AStarHeuristic.html">AStarHeuristic</a> h, const bgl_named_params&lt;P, T, R&gt;&amp; params);
<i>// Non-named parameter interface</i>
template &lt;typename VertexListGraph, typename AStarHeuristic,
typename <a href="AStarVisitor.html">AStarVisitor</a>, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap, typename VertexIndexMap,
typename ColorMap,
typename <a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">CompareFunction</a>, typename <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">CombineFunction</a>,
typename CostInf, typename CostZero&gt;
inline void
astar_search
(VertexListGraph &amp;g,
typename graph_traits&lt;VertexListGraph&gt;::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
VertexIndexMap index_map, ColorMap color,
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero);
</PRE>
<P>
This algorithm implements a heuristic search on a weighted, directed
or undirected graph for the case where all edge weights are
non-negative.
</P>
<P>
The A* algorithm is a <i>heuristic graph search algorithm</i>: an A*
search is "guided" by a <i>heuristic function</i>. A heuristic
function <i>h(v)</i> is one which estimates the cost from a non-goal
state (<i>v</i>) in the graph to some goal state, <i>g</i>.
Intuitively, A* follows paths (through the graph) to the goal that are
estimated by the heuristic function to be the best paths. Unlike
best-first search, A* takes into account the known cost from the start
of the search to <i>v</i>; the paths A* takes are guided by a function
<i>f(v) = g(v) + h(v)</i>, where <i>h(v)</i> is the heuristic
function, and <i>g(v)</i> (sometimes denoted <i>c(s, v)</i>) is the
known cost from the start to <i>v</i>. Clearly, the efficiency of A*
is highly dependent on the heuristic function with which it is used.
</P>
<P>
The A* algorithm is very similar to Dijkstra's Shortest Paths
algorithm. This implementation finds all the shortest paths from the
start vertex to every other vertex by creating a search tree,
examining vertices according to their remaining cost to some goal, as
estimated by a heuristic function. Most commonly, A* is used to find
some specific goal vertex or vertices in a graph, after which the
search is terminated.
</P>
<P>
A* is particularly useful for searching <i>implicit</i> graphs.
Implicit graphs are graphs that are not completely known at the
beginning of the search. Upon visiting a vertex, its neighbors are
"generated" and added to the search. Implicit graphs are particularly
useful for searching large state spaces -- in gameplaying scenarios
(e.g. chess), for example -- in which it may not be possible to store
the entire graph. Implicit searches can be performed with this
implementation of A* by creating special visitors that generate
neighbors of newly-expanded vertices.
</P>
<P>
This implementation of A* is based on an OPEN/CLOSED list formulation
of the algorithm. Vertices on the OPEN list have been ``discovered''
by the algorithm, but not ``expanded'' (we have not discovered their
adjacent vertices). Vertices on the CLOSED list have been completely
examined by our search (we have expanded them and added their children
to the OPEN list). Vertices that are on neither list have not been
encountered in any context so far in our search. A major advantage of
this formulation of the A* algorithm over other approaches is that it
avoids ``cycles'' in the state space; the search will not become
trapped by loops in the graph. The OPEN/CLOSED lists are implemented
using BGL's vertex coloring mechanisms. Vertices in OPEN are colored
gray, vertices in CLOSED are colored black, and undiscovered vertices
are colored white.
</P>
<P>
The criteria for expanding a vertex on the OPEN list is that it has
the lowest <i>f(v) = g(v) + h(v)</i> value of all vertices on OPEN.
Cost information about vertices is stored in a property map.
</P>
<P>
The following is the pseudocode for the A* heuristic search algorithm.
In the pseudocode, <i>h</i> is the heuristic function, <i>w</i> is the
edge weight, <i>d</i> is the distance of a vertex from <i>s</i>, and
<i>Q</i> is a priority queue, sorted by <i>f</i>, the estimated cost
to the goal of the path through a vertex. <i>p</i> is a predecessor
map. The visitor event points for the algorithm are indicated by the
labels on the right.
</P>
<table>
<tr>
<td valign="top">
<pre>
A*(<i>G</i>, <i>s</i>, <i>h</i>)
<b>for</b> each vertex <i>u in V</i>
<i>d[u] := f[u] := infinity</i>
<i>color[u] :=</i> WHITE
<i>p[u] := u</i>
<b>end for</b>
<i>color[s] :=</i> GRAY
<i>d[s] := 0</i>
<i>f[s] := h(s)</i>
INSERT(<i>Q, s</i>)
<b>while</b> (<i>Q != &Oslash;</i>)
<i>u :=</i> EXTRACT-MIN(<i>Q</i>)
<b>for</b> each vertex <i>v in Adj[u]</i>
<b>if</b> (<i>w(u,v) + d[u] &lt; d[v]</i>)
<i>d[v] := w(u,v) + d[u]</i>
<i>f[v] := d[v] + h(v)</i>
<i>p[v] := u</i>
<b>if</b> (<i>color[v] =</i> WHITE)
<i>color[v] :=</i> GRAY
INSERT(<i>Q, v</i>)
<b>else if</b> (<i>color[v] =</i> BLACK)
<i>color[v] :=</i> GRAY
INSERT(<i>Q, v</i>)
<b>end if</b>
<b>else</b>
<i>...</i>
<b>end for</b>
<i>color[u] :=</i> BLACK
<b>end while</b>
</pre>
</td>
<td valign="top">
<pre>
initialize vertex <i>u</i>
discover vertex <i>s</i>
examine vertex <i>u</i>
examine edge <i>(u,v)</i>
edge <i>(u,v)</i> relaxed
discover vertex <i>v</i>
reopen vertex <i>v</i>
edge <i>(u,v)</i> not relaxed
finish vertex <i>u</i>
</pre>
</td>
</tr>
</table>
<h3>Where Defined</h3>
<a href="../../../boost/graph/astar_search.hpp"><tt>boost/graph/astar_search.hpp</tt></a>
<h3>Parameters</h3>
IN: <tt>VertexListGraph&amp; g</tt>
<blockquote>
The graph object on which the algorithm will be applied. The type
<tt>VertexListGraph</tt> must be a model of the <a
href="VertexListGraph.html">
Vertex List Graph</a> concept.
</blockquote>
IN: <tt>vertex_descriptor s</tt>
<blockquote>
The start vertex for the search. All distances will be calculated
from this vertex, and the shortest paths tree (recorded in the
predecessor map) will be rooted at this vertex.
</blockquote>
IN: <tt>AStarHeuristic h</tt>
<blockquote>
The heuristic function that guides the search. The type
<tt>AStarHeuristic</tt> must be a model of the <a href="AStarHeuristic.html">AStarHeuristic</a>
concept.
</blockquote>
<h3>Named Parameters</h3>
IN: <tt>weight_map(WeightMap w_map)</tt>
<blockquote>
The weight or ``length'' of each edge in the graph. The weights
must all be non-negative; the algorithm will throw a <a
href="./exception.html#negative_edge"><tt>negative_edge</tt></a>
exception if one of the edges is negative. The type
<tt>WeightMap</tt> must be a model of <a
href="../../property_map/ReadablePropertyMap.html"><tt>Readable
Property Map</tt></a>. The edge descriptor type of the graph needs
to be usable as the key type for the weight map. The value type
for this map must be the same as the value type of the distance
map.<br>
<b>Default:</b> <tt>get(edge\_weight, g)</tt>
</blockquote>
IN: <tt>vertex_index_map(VertexIndexMap i_map)</tt>
<blockquote>
This maps each vertex to an integer in the range <tt>[0,
num_vertices(g))</tt>. This is necessary for efficient updates of
the heap data structure when an edge is relaxed. The type
<tt>VertexIndexMap</tt> must be a model of <a
href="../../property_map/ReadablePropertyMap.html"><tt>Readable
Property Map</tt></a>. The value type of the map must be an integer
type. The vertex descriptor type of the graph needs to be usable as
the key type of the map.<br>
<b>Default:</b> <tt>get(vertex_index, g)</tt>
</blockquote>
OUT: <tt>predecessor_map(PredecessorMap p_map)</tt>
<blockquote>
The predecessor map records the edges in the minimum spanning tree.
Upon completion of the algorithm, the edges <tt>(p[u],u)</tt> for
all <tt>u</tt> in <tt>V</tt> are in the minimum spanning tree. If
<tt>p[u] = u</tt> then <tt>u</tt> is either the start vertex or a
vertex that is not reachable from the start. The
<tt>PredecessorMap</tt> type must be a <a
href="../../property_map/ReadWritePropertyMap.html"><tt>Read/Write
Property Map</tt></a> with key and vertex types the same as the
vertex descriptor type of the graph.<br>
<b>Default:</b> <tt>dummy_property_map</tt>
</blockquote>
UTIL/OUT: <tt>distance_map(DistanceMap d_map)</tt>
<blockquote>
The shortest path weight from the start vertex <tt>s</tt> to each
vertex in the graph <tt>g</tt> is recorded in this property map.
The shortest path weight is the sum of the edge weights along the
shortest path. The type <tt>DistanceMap</tt> must be a model of <a
href="../../property_map/ReadWritePropertyMap.html"><tt>Read/Write
Property Map</tt></a>. The vertex descriptor type of the graph
needs to be usable as the key type of the distance map. The value
type of the distance map is the element type of a <a
href="./Monoid.html"><tt>Monoid</tt></a> formed with the
<tt>combine</tt> function object and the zero object for the
identity element. Also the distance value type must have a <a
href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html"><tt>StrictWeakOrdering</tt></a>
provided by the <tt>compare</tt> function object.<br>
<b>Default:</b> <tt>iterator_property_map</tt> created from a
<tt>std::vector</tt> with the same value type as the
<tt>WeightMap</tt>, and of size <tt>num_vertices(g)</tt>, and using
the <tt>i_map</tt> for the index map.
</blockquote>
UTIL/OUT: <tt>rank_map(CostMap c_map)</tt>
<blockquote>
The <i>f</i>-value for each vertex. The <i>f</i>-value is defined
as the sum of the cost to get to a vertex from the start vertex, and
the estimated cost (as returned by the heuristic function
<tt>h</tt>) from the vertex to a goal. The type <tt>CostMap</tt>
must be a model of <a
href="../../property_map/ReadWritePropertyMap.html"><tt>Read/Write
Property Map</tt></a>. The vertex descriptor type of the graph
needs to be usable as the key type of the distance map. The value
type of the distance map is the element type of a <a
href="./Monoid.html"><tt>Monoid</tt></a> formed with the
<tt>combine</tt> function object and the zero object for the
identity element. Also the distance value type must have a <a
href="http://www.sgi.com/tech/stl/StrictWeakOrdering.html"><tt>StrictWeakOrdering</tt></a>
provided by the <tt>compare</tt> function object. The value type
for this map must be the same as the value type for the distance
map.<br>
<b>Default:</b> <tt>iterator_property_map</tt> created from a
<tt>std::vector</tt> with the same value type as the
<tt>WeightMap</tt>, and of size <tt>num_vertices(g)</tt>, and using
the <tt>i_map</tt> for the index map.
</blockquote>
UTIL/OUT: <tt>color_map(ColorMap c_map)</tt>
<blockquote>
This is used during the execution of the algorithm to mark the
vertices, indicating whether they are on the OPEN or CLOSED lists.
The vertices start out white and become gray when they are inserted
into the OPEN list. They then turn black when they are examined and
placed on the CLOSED list. At the end of the algorithm, vertices
reachable from the source vertex will have been colored black. All
other vertices will still be white. The type <tt>ColorMap</tt> must
be a model of <a
href="../../property_map/ReadWritePropertyMap.html"><tt>Read/Write
Property Map</tt></a>. A vertex descriptor must be usable as the
key type of the map, and the value type of the map must be a model
of <a href="./ColorValue.html"><tt>Color Value</tt></a>.<br>
<b>Default:</b> <tt>iterator_property_map</tt> created from a
<tt>std::vector</tt> of value type <tt>default_color_type</tt>, with
size <tt>num_vertices(g)</tt>, and using the <tt>i_map</tt> for the
index map.
</blockquote>
IN: <tt>distance_compare(CompareFunction cmp)</tt>
<blockquote>
This function is use to compare distances to determine which vertex
is closer to the start vertex, and to compare <i>f</i>-values to
determine which vertex on the OPEN list to examine next. The
<tt>CompareFunction</tt> type must be a model of <a
href="http://www.sgi.com/tech/stl/BinaryPredicate.html"><tt>Binary
Predicate</tt></a> and have argument types that match the value type
of the <tt>DistanceMap</tt> property map.<br>
<b>Default:</b> <tt>std::less&lt;D&gt;</tt> with <tt>D = typename
property_traits&lt;DistanceMap&gt;::value_type</tt>.
</blockquote>
IN: <tt>distance_combine(CombineFunction cmb)</tt>
<blockquote>
This function is used to combine distances to compute the distance
of a path, and to combine distance and heuristic values to compute
the <i>f</i>-value of a vertex. The <tt>CombineFunction</tt> type
must be a model of <a
href="http://www.sgi.com/tech/stl/BinaryFunction.html"><tt>Binary
Function</tt></a>. Both argument types of the binary function must
match the value type of the <tt>DistanceMap</tt> property map (which
is the same as that of the <tt>WeightMap</tt> and <tt>CostMap</tt>
property maps). The result type must be the same type as the
distance value type.<br>
<b>Default:</b> <tt>std::plus&lt;D&gt;</tt> with <tt>D = typename
property_traits&lt;DistanceMap&gt;::value_type</tt>.
</blockquote>
IN: <tt>distance_inf(D inf)</tt>
<blockquote>
The <tt>inf</tt> object must be the greatest value of any <tt>D</tt>
object. That is, <tt>compare(d, inf) == true</tt> for any <tt>d !=
inf</tt>. The type <tt>D</tt> is the value type of the
<tt>DistanceMap</tt>.<br>
<b>Default:</b> <tt>std::numeric_limits&lt;D&gt;::max()</tt>
</blockquote>
IN: <tt>distance_zero(D zero)</tt>
<blockquote>
The <tt>zero</tt> value must be the identity element for the <a
href="./Monoid.html"><tt>Monoid</tt></a> formed by the distance
values and the <tt>combine</tt> function object. The type
<tt>D</tt> is the value type of the <tt>DistanceMap</tt>.<br>
<b>Default</b>: <tt>D()</tt> with <tt>D = typename
property_traits&lt;DistanceMap&gt;::value_type</tt>.
</blockquote>
OUT: <tt>visitor(AStarVisitor v)</tt>
<blockquote>
Use this to specify actions that you would like to happen during
certain event points within the algorithm. The type
<tt>AStarVisitor</tt> must be a model of the <a
href="AStarVisitor.html"><tt>AStarVisitor</tt></a> concept. The
visitor object is passed by value <a href="#1">[1]</a>.<br>
<b>Default:</b> <tt>astar_visitor&lt;null_visitor&gt;</tt>
</blockquote>
<H3>Complexity</H3>
<P>
The time complexity is <i>O((E + V) log V)</i>.
<h3>Visitor Event Points</h3>
<ul>
<li><b><tt>vis.initialize_vertex(u, g)</tt></b>
is invoked on each vertex in the graph before the start of the
algorithm.
<li><b><tt>vis.discover_vertex(v, g)</tt></b>
is invoked when a vertex is first discovered and is added to the
OPEN list.
<li><b><tt>vis.examine_vertex(u, g)</tt></b>
is invoked when a vertex is popped from
the queue (i.e., it has the lowest cost on the OPEN list).
<li><b><tt>vis.examine_edge(e, g)</tt></b>
is invoked on each out-edge of a vertex immediately after it is
examined.
<li><b><tt>vis.edge_relaxed(e, g)</tt></b>
is invoked on edge <i>(u,v)</i> if <i>d[u] + w(u,v) < d[v]</i>.
<li><b><tt>vis.edge_not_relaxed(e, g)</tt></b>
is invoked if the edge is not relaxed (see above).
<li><b><tt>vis.black_target(u, g)</tt></b>
is invoked when a vertex that is on the CLOSED list is
"rediscovered" via a more efficient path, and is re-added to the
OPEN list.
<li><b><tt>vis.finish_vertex(u, g)</tt></b>
is invoked on a vertex when it is added to the CLOSED list, which
happens after all of its out edges have been examined.
</ul>
<H3>Example</H3>
<P>
See <a href="../example/astar-cities.cpp">
<TT>example/astar-cities.cpp</TT></a> for an example of
using A* search.
<H3>Notes</H3>
<a name="1">[1]</a> Since the visitor parameter is passed by value, if
your visitor contains state then any changes to the state during the
algorithm will be made to a copy of the visitor object, not the
visitor object passed in. Therefore you may want the visitor to hold
this state by pointer or reference.
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2004</TD><TD>
<A HREF="http://www.cs.rpi.edu/~beevek/">Kristopher Beevers</A>,
Rensselaer Polytechnic Institute (<A
HREF="mailto:beevek@cs.rpi.edu">beevek@cs.rpi.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

112
doc/astar_visitor.html Normal file
View File

@ -0,0 +1,112 @@
<HTML>
<!--
-- Copyright (c) 2004 Kris Beevers
--
-- Permission to use, copy, modify, distribute and sell this software
-- and its documentation for any purpose is hereby granted without fee,
-- provided that the above copyright notice appears in all copies and
-- that both that copyright notice and this permission notice appear
-- in supporting documentation. We make no
-- representations about the suitability of this software for any
-- purpose. It is provided "as is" without express or implied warranty.
-->
<Head>
<Title>Boost Graph Library: astar_visitor</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../c++boost.gif"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1>
<pre>
astar_visitor&lt;EventVisitorList&gt;
</pre>
</H1>
This class is an adapter that converts a list of <a
href="./EventVisitor.html">EventVisitor</a>'s (constructed using
<tt>std::pair</tt>) into a <a
href="./AStarVisitor.html">AStarVisitor</a>.
<h3>Example</h3>
See the example for <a href="./EventVisitor.html">EventVisitor</a>.
<h3>Model of</h3>
<a href="./AStarVisitor.html">AStarVisitor</a>
<H3>Template Parameters</H3>
<P>
<TABLE border>
<TR>
<th>Parameter</th><th>Description</th><th>Default</th>
</tr>
<TR><TD><TT>EventVisitorList</TT></TD>
<TD>
A list of <a href="./EventVisitor.html">EventVisitor</a>'s created
with <tt>std::pair</tt>.
</TD>
<TD><TT><a href="./null_visitor.html"><tt>null_visitor</tt></a></TT></TD>
</TR>
</table>
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/astar_search.hpp">
<TT>boost/graph/astar_search.hpp</TT></a>
<h3>Member Functions</h3>
This class implements all of the member functions required by <a
href="./AStarVisitor.html">AStarVisitor</a>. In each function the
appropriate event is dispatched to the <a
href="./EventVisitor.html">EventVisitor</a>'s in the
EventVisitorList.
<h3>Non-Member Functions</h3>
<table border>
<tr>
<th>Function</th><th>Description</th>
</tr>
<tr><td><tt>
template &lt;class EventVisitorList&gt;<br>
astar_visitor&lt;EventVisitorList&gt;<br>
make_astar_visitor(EventVisitorList ev_list);
</tt></td><td>
Returns the event visitor list adapted to be an A* visitor.
</td></tr>
</table>
<h3>See Also</h3>
<a href="./visitor_concepts.html">Visitor concepts</a>
<p>
The following are event visitors: <a
href="./predecessor_recorder.html"><tt>predecessor_recorder</tt></a>,
<a href="./distance_recorder.html"><tt>distance_recorder</tt></a>,
<a href="./time_stamper.html"><tt>time_stamper</tt></a>,
and <a href="./property_writer.html"><tt>property_writer</tt></a>.
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2004</TD><TD>
<A HREF="http://www.cs.rpi.edu/~beevek/">Kristopher Beevers</A>,
Rensselaer Polytechnic Institute (<A
HREF="mailto:beevek@cs.rpi.edu">beevek@cs.rpi.edu</A>)
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -352,7 +352,12 @@ Technical Report BN9/71, Stichting Mahtematisch Centrum, Amsterdam, 1971.
<dd>T. Kamada and S. Kawai<br>
<em>An algorithm for drawing general undirected graphs.</em><br>
Information Processing Letters, 31, pp. 7-15, 1989.
</DL>
<p></p><dt><a name="fruchterman91">58</a>
<dd>T. Fruchterman and E. Reingold<br>
<em>Graph drawing by force-directed placement.</em><br>
Software--Practice & Experience, 21 (11), pp. 1129-1164, 1991.
</dl>
<br>
<HR>

View File

@ -0,0 +1,160 @@
<HTML>
<Head>
<Title>Johnson All Pairs Shortest Paths</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../boost.png"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<H1><A NAME="sec:floyd-warshall">
<TT>floyd_warshall_all_pairs_shortest_paths</TT>
</H1>
<PRE><em>// Named parameters version</em>
template &lt;class VertexListGraph, class DistanceMatrix,
class P, class T, class R&gt;
bool floyd_warshall_initialized_all_pairs_shortest_paths(
const VertexListGraph&amp; g, DistanceMatrix&amp; d,
const bgl_named_params&lt;P, T, R&gt;&amp; params)
template &lt;class VertexAndEdgeListGraph, class DistanceMatrix,
class P, class T, class R&gt;
bool floyd_warshall_all_pairs_shortest_paths(
const VertexAndEdgeListGraph&amp; g, DistanceMatrix&amp; d,
const bgl_named_params&lt;P, T, R&gt;&amp; params)
<em>// Positional parameter versions</em>
\begin{verbatim}
template &lt;typename VertexListGraph, typename DistanceMatrix,
typename BinaryPredicate, typename BinaryFunction,
typename Infinity, typename Zero&gt;
bool floyd_warshall_initialized_all_pairs_shortest_paths(
const VertexListGraph&amp; g, DistanceMatrix&amp; d,
const BinaryPredicate&amp; compare, const BinaryFunction&amp; combine,
const Infinity&amp; inf, const Zero&amp; zero)
template &lt;typename VertexAndEdgeListGraph, typename DistanceMatrix,
typename WeightMap, typename BinaryPredicate,
typename BinaryFunction, typename Infinity, typename Zero&gt;
bool floyd_warshall_all_pairs_shortest_paths(
const VertexAndEdgeListGraph&amp; g, DistanceMatrix&amp; d,
const WeightMap&amp; w, const BinaryPredicate&amp; compare,
const BinaryFunction&amp; combine,
const Infinity&amp; inf, const Zero&amp; zero)</PRE>
<P>
These algorithms find the shortest distance between every pair of
vertices in the graph. The algorithms return false if there is a
negative weight cycle in the graph, true otherwise. The shortest
distance between each pair of vertices is stored in the distance
matrix <code>d</code>. The difference between the two algorithms is in
whether the distance matrix is assumed to be initialized or not, as
discussed below under the OUT parameter description.
<P>This algorithm should be used to compute shortest paths between
every pair of vertices for dense graphs. For sparse graphs, use <a
href="johnson_all_pairs_shortest.html"><code>johnson_all_pairs_shortest_paths</code></a>.
<H3>Where Defined</H3>
<P>
<a href="../../../boost/graph/floyd_warshall_shortest.hpp"><TT>boost/graph/floyd_warshall_shortest.hpp</TT></a>
<h3>Parameters</h3>
IN: <code>Graph&amp; g</code>
<blockquote>
A directed or undirected graph. The graph must be a model of <a href="VertexListGraph.html">Vertex List Graph</a> for calls to
<code>floyd_warshall_initialized_all_pairs_shortest_paths</code>, and
<a href="VertexAndEdgeListGraph.html">Vertex And Edge List Graph</a> for calls to
<code>floyd_warshall_all_pairs_shortest_paths</code>.<br>
</blockquote>
OUT: <code>DistanceMatrix&amp; d</code>
<blockquote>
The length of the shortest path between each pair of vertices
<code>u</code>,<code>v</code> are
stored in the matrix at location <code>D[u][v]</code>. The
DistanceMatrix must be
of type <code>{M, I, V}</code> where <code>I</code> is of type
<code>vertex_descriptor</code> and <code>V</code> is the
type of the <code>weight_map</code>. The set of types must be a model of
<a href="BasicMatrix.html">BasicMatrix</a>, with the exceptions that
it isn't required to
run in constant time, and it must be mutable. The matrix must be
properly initialized when it is passed to the function
<code>floyd_warshall_initialized_all_pairs_shortest_paths</code>. If the
function <code>floyd_warshall_all_pairs_shortest_paths</code> is used then the
matrix will be initialized for the user.
</blockquote>
<h3>Named Parameters</h3>
IN: <code>weight_map(WeightMap w)</code>
<blockquote>
The weight of length of each edge in the graph. The <code>WeightMap</code>
must be a model of <a href="../../property_map/ReadablePropertyMap.html">Readable Property
Map</a>. The edge descriptor
type of the graph needs to be usable as the key type for the weight
map. The <code>value_type</code> of the weight map must be the type of the
<code>DistanceMatrix</code>, and must always either be part of the
graph passed to the function, or passed in as a parameter.<br>
<b>Default:</b> <code>get(edge_weight, g)</code>
</blockquote>
IN: <code>distance_compare(CompareFunction cmp)</code>
<blockquote>
The function used to compare distances to determine which target
vertex is closer to the source vertex. The CompareFunction must be a
model of <code>BinaryPredicate</code>. The argument types must match the
value type of the <code>WeightMap</code>.<br>
<b>Default:</b> <code>std::less&lt;WM&gt;</code>with <code>WM = typename property_traits&lt;WeightMap&gt;::value_type</code>
</blockquote>
IN: <code>distance_combine(CombineFunction cmb)</code>
<blockquote>
The function used to combine distance to compute the distance of a
path. The CombineFunction must be a model of <code>BinaryFunction</code>.
The argument types must match the value type of the <code>WeightMap</code>.
The result type must be the same as the distance value type.<br>
<b>Default:</b> <code>std::plus&lt;WM&gt;</code> with <code>WM = typename property_traits&lt;WeightMap&gt;::value_type</code>
</blockquote>
IN: <code>distance_inf(WM inf)</code>
<blockquote>
The value used to initialize the distance for each vertex before
starting the algorithm, and to represent the distance between vertices
for which there is not path. Should be larger than any possible valid
path length. The argument type must match the value type of the <code>
WeightMap</code>.<br>
<b>Default:</b> <code>std::numeric_limits&lt;WM&gt;::max()</code> with <code>WM = typename property_traits&lt;WeightMap&gt;::value_type</code>
</blockquote>
IN: <code>distance_zero(WM zero)</code>
<blockquote>
The value used to represent the distance from a vertex to itself, and
to determine if a value is negative. The argument type must match the
value type of the <code>WeightMap</code>.<br>
<b>Default:</b> <code>0</code>
</blockquote>
<h3>Complexity</h3>
The time complexity is <i>O(V<sup>3</sup>)</i>.
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2002-2004</TD><TD>
Lauren Foutz, Rensselaer Polytechnic Institute</td>
</tr><tr valign="top"><td></td>
<td>Scott Hill, Rensselaer Polytechnic Institute
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -0,0 +1,206 @@
<HTML>
<Head>
<Title>Boost Graph Library: Fruchterman-Reingold Force-Directed Layout</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../boost.png"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<TT>fruchterman_reingold_force_directed_layout</TT>
</H1>
<P>
<PRE>
<i>// named parameter version</i>
template&lt;typename Graph, typename PositionMap, typename Dim, typename Param,
typename Tag, typename Rest&gt;
void
fruchterman_reingold_force_directed_layout
(const Graph& g,
PositionMap position,
Dim width,
Dim height,
const bgl_named_params&lt;Param, Tag, Rest&gt;&amp; params);
<i>// non-named parameter version</i>
template&lt;typename Graph, typename PositionMap, typename Dim,
typename AttractiveForce, typename RepulsiveForce,
typename ForcePairs, typename DisplacementMap, typename Cooling&gt;
void
fruchterman_reingold_force_directed_layout
(const Graph&amp; g,
PositionMap position,
Dim width,
Dim height,
AttractiveForce fa,
RepulsiveForce fr,
ForcePairs fp,
Cooling cool,
DisplacementMap displacement);
template&lt;typename Graph, typename PositionMap, typename Dim&gt;
void
fruchterman_reingold_force_directed_layout(const Graph& g,
PositionMap position,
Dim width,
Dim height);
</PRE>
<P> This algorithm&nbsp;[<A
HREF="bibliography.html#fruchterman91">58</A>] performs layout of
unweighted, undirected graphs. Unlike the <a
href="kamada_kawai_spring_layout.html">Kamada-Kawai</a> layout
algorithm, this algorithm directly supports the layout of disconnected
graphs (but see the <tt>force_pairs</tt> named parameter). It is a
<em>force-directed</em> algorithm, meaning that vertex layout is
determined by the forces pulling vertices together and pushing them
apart. Attractive forces occur between adjacent vertices only, whereas
repulsive forces occur between every pair of vertices. Each iteration
computes the sum of the forces on each vertex, then moves the vertices
to their new positions. The movement of vertices is mitigated by the
<i>temperature</i> of the system for that iteration: as the algorithm
progresses through successive iterations, the temperature should
decrease so that vertices settle in place. The cooling schedule,
attractive forces, and repulsive forces can be provided by the user.
<p> The vertices are often placed randomly prior to execution of this algorithm via <a href="random_layout.html"><tt>random_graph_layout</tt></a>.
<h3>Where Defined</h3>
<a href="../../../boost/graph/fruchterman_reingold.hpp"><tt>boost/graph/fruchterman_reingold.hpp</tt></a>
<h3>Parameters</h3>
IN: <tt>const Graph&amp; g</tt>
<blockquote>
The graph object on which the algorithm will be applied.
The type <tt>Graph</tt> must be a model of
<a href="./VertexAndEdgeListGraph.html">Vertex And Edge List Graph</a>.
</blockquote>
IN/OUT: <tt>PositionMap position</tt>
<blockquote>
The property map that stores the position of each vertex. It should
typically be initialized with the vertices at random locations (use
<a href="random_layout.html"><tt>random_graph_layout</tt></a>). The
type <tt>PositionMap</tt> must be a model of <a
href="../../property_map/LvaluePropertyMap.html">Lvalue Property
Map</a> such that the vertex descriptor type of <tt>Graph</tt> is
convertible to its key type. Its value type must be a structure
with fields <tt>x</tt> and <tt>y</tt>, representing the coordinates
of the vertex.
</blockquote>
IN: <tt>Dim width</tt>
<blockquote>
The width of the display area in which layout should occur. On
termination of the algorithm, the <tt>x</tt> coordinates of all
vertices will fall in <tt>[-width/2, width/2]</tt>.
</blockquote>
IN: <tt>Dim height</tt>
<blockquote>
The height of the display area in which layout should occur. On
termination of the algorithm, the <tt>y</tt> coordinates of all
vertices will fall in <tt>[-height/2, height/2]</tt>.
</blockquote>
<h3>Named Parameters</h3>
IN: <tt>attractive_force(AttractiveForce fa)</tt>
<blockquote>
Computes the magnitude of the attractive force between two adjacent
vertices. The function object <tt>fa</tt> must accept four
parameters: the edge descriptor, <tt>k</tt>, the distance between the
vertices, and the graph. <tt>k</tt> is the square root of the ratio
of the display area to the number of vertices. <br>
<b>Default:</b> <tt>square_distance_attractive_force()</tt>, which
computes the attractive force as <code>dist<sup>2</sup>/k</code>.
</blockquote>
IN: <tt>repulsive_force(RepulsiveForce fr)</tt>
<blockquote>
Computes the magnitude of the repulsive force between any two
vertices. The function object <tt>fa</tt> must accept five
parameters: the two vertex descriptors, <tt>k</tt>, the distance between the
vertices, and the graph. <tt>k</tt> is the square root of the ratio
of the display area to the number of vertices. <br>
<b>Default:</b> <tt>square_distance_repsulsive_force()</tt>, which
computes the repulsive force as <code>k<sup>2</sup>/dist</code>.
</blockquote>
IN: <tt>force_pairs(ForcePairs fp)</tt>
<blockquote>
Enumerates the pairs of vertices on which the repulsive force should
be applied. <tt>fp</tt> is a function object taking two parameters:
the graph <tt>g</tt> and a binary function object that should be
passed each pair of vertices to be considered. The basic formulation
of the Fruchterman-Reingold algorithm computes repulsive forces
between all pairs of vertices (pass <tt>all_force_pairs()</tt> for
this parameter), which is functional for disconnected graphs but
tends to push the connected components toward the edges of the
display area. The grid variant of the algorithm places a grid over
the display area and only computes repulsive forces among vertices
within each rectangle in the grid. The grid variant can be more
efficient than the basic formulation and tends to produce better
layouts for disconnected graphs, but is not better overall: pass
<tt>make_grid_force_pairs(width, height, position)</tt> as this
parameter to use the grid variant. Other enumeration strategies may
yield better results for particular graphs. <br>
<b>Default:</b> <tt>make_grid_force_pairs(width, height, position)</tt>
</blockquote>
IN: <tt>cooling(Cooling cool)</tt>
<blockquote>
Determines the cooling schedule for the algorithm, which affects the
rate of movement of vertices and termination of the algorithm. The
<tt>cool</tt> parameter is a nullary function object (i.e., one that
takes no arguments) and returns the temperature for the current
iteration. When the returned temperature is zero, the algorithm
terminates. Cooling schedules should begin with some initial
temperature and gradually reduce the temperature to zero.<br>
<b>Default:</b> <tt>linear_cooling&lt;double&gt;(100)</tt>
</blockquote>
UTIL: <tt>displacement_map(DisplacementMap displacement)</tt>
<blockquote>
The displacement map is used to compute the amount by which each
vertex will move in each step. The <tt>DisplacementMap</tt> type
carries the same requirements as the <tt>PositionMap</tt> type.<br>
<b>Default:</b> An <tt>iterator_property_map</tt> with a value type
of <tt>simple_point&lt;double&gt;</tt> and using the given vertex index map.
</blockquote>
IN: <tt>vertex_index_map(VertexIndexMap i_map)</tt>
<blockquote>
This maps each vertex to an integer in the range <tt>[0,
num_vertices(g))</tt>. This is only necessary when no
displacement map is provided.
The type <tt>VertexIndexMap</tt> must be a model of <a
href="../../property_map/ReadablePropertyMap.html">Readable Property
Map</a>. The value type of the map must be an integer type. The
vertex descriptor type of the graph needs to be usable as the key
type of the map.<br>
<b>Default:</b> <tt>get(vertex_index, g)</tt>
</blockquote>
<H3>Complexity</H3>
<P> The time complexity is <i>O(|V|<sup>2</sup> + |E|)</i> for each
iteration of the algorithm in the worse case. The average case for the
grid variant is <i>O(|V| + |E|)</i>. The number of iterations is
determined by the cooling schedule.
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy 2004</TD><TD>
<A HREF="../../../people/doug_gregor.html">Doug Gregor</A>, Indiana University
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -46,7 +46,9 @@ between each pair of vertices is stored in the distance matrix
<TT>D</TT>. This is one of the more time intensive graph algorithms,
having a time complexity of <i>O(V E log V)</i>.
<P>
<P>This algorithm should be used to compute shortest paths between
every pair of vertices for sparse graphs. For dense graphs, use <a
href="floyd_warshall_shortest.html"><code>floyd_warshall_all_pairs_shortest_paths</code></a>.
<H3>Where Defined</H3>

94
doc/random_layout.html Normal file
View File

@ -0,0 +1,94 @@
<HTML>
<Head>
<Title>Boost Graph Library: Random Graph Layout</Title>
<BODY BGCOLOR="#ffffff" LINK="#0000ee" TEXT="#000000" VLINK="#551a8b"
ALINK="#ff0000">
<IMG SRC="../../../boost.png"
ALT="C++ Boost" width="277" height="86">
<BR Clear>
<TT>random_graph_layout</TT>
</H1>
<P>
<PRE>
<i>// non-named parameter version</i>
template&lt;typename Graph, typename PositionMap, typename Dimension,
typename RandomNumberGenerator&gt;
void
random_graph_layout(const Graph&amp; g, PositionMap position_map,
Dimension minX, Dimension maxX,
Dimension minY, Dimension maxY,
RandomNumberGenerator&amp; gen);
</PRE>
<P> This algorithm places the points of the graph at random
locations. </p>
<h3>Where Defined</h3>
<a href="../../../boost/graph/random_layout.hpp"><tt>boost/graph/random_layout.hpp</tt></a>
<h3>Parameters</h3>
IN: <tt>const Graph&amp; g</tt>
<blockquote>
The graph object on which the algorithm will be applied.
The type <tt>Graph</tt> must be a model of
<a href="./VertexAndEdgeListGraph.html">Vertex And Edge List Graph</a>.
</blockquote>
IN/OUT: <tt>PositionMap position</tt>
<blockquote>
The property map that stores the position of each vertex. The type
<tt>PositionMap</tt> must be a model of <a
href="../../property_map/LvaluePropertyMap.html">Lvalue Property
Map</a> such that the vertex descriptor type of <tt>Graph</tt> is
convertible to its key type. Its value type must be a structure with
fields <tt>x</tt> and <tt>y</tt>, representing the coordinates of
the vertex.
</blockquote>
IN: <tt>Dimension minX</tt>
<blockquote>
The minimum <tt>x</tt> coordinate.
</blockquote>
IN: <tt>Dimension maxX</tt>
<blockquote>
The maximum <tt>x</tt> coordinate.
</blockquote>
IN: <tt>Dimension minY</tt>
<blockquote>
The minimum <tt>y</tt> coordinate.
</blockquote>
IN: <tt>Dimension maxY</tt>
<blockquote>
The maximum <tt>y</tt> coordinate.
</blockquote>
IN/UTIL: <tt>RandomNumberGenerator&amp; gen</tt>
<blockquote>
A random number generator that will be used to place vertices. The
type <tt>RandomNumberGenerator</tt> must model the <a
href="../../random/random-concepts.html#number_generator">NumberGenerator</a>
concept.
</blockquote>
<H3>Complexity</H3>
<P> The time complexity is <i>O(|V|)</i>.
<br>
<HR>
<TABLE>
<TR valign=top>
<TD nowrap>Copyright &copy; 2004</TD><TD>
<A HREF="../../../people/doug_gregor.html">Doug Gregor</A>, Indiana University
</TD></TR></TABLE>
</BODY>
</HTML>

View File

@ -73,6 +73,7 @@
<LI><a href="./DFSVisitor.html">DFS Visitor</a>
<LI><a href="./DijkstraVisitor.html">Dijkstra Visitor</a>
<LI><a href="./BellmanFordVisitor.html">Bellman Ford Visitor</a>
<LI><a href="AStarVisitor.html">A* Visitor</a></LI>
<LI><a href="./EventVisitor.html">Event Visitor</a>
</OL>
<li>EventVisitorList Adaptors
@ -82,6 +83,7 @@
<LI><a href="./dfs_visitor.html"><tt>dfs_visitor</tt></a>
<LI><a href="./dijkstra_visitor.html"><tt>dijkstra_visitor</tt></a>
<LI><a href="./bellman_visitor.html"><tt>bellman_visitor</tt></a>
<li><a href="astar_visitor.html"><tt>astar_visitor</tt></a></li>
</OL>
<li>Event Visitors
<OL>
@ -142,6 +144,7 @@
<LI><A href="./dag_shortest_paths.html"><tt>dag_shortest_paths</tt></A>
<LI><A
href="./johnson_all_pairs_shortest.html"><tt>johnson_all_pairs_shortest_paths</tt></A>
<li><a href="floyd_warshall_shortest.html"><tt>floyd_warshall_all_pairs_shortest_paths</tt></a></li>
</OL>
<LI>Minimum Spanning Tree Algorithms
<OL>
@ -184,8 +187,10 @@
<LI><A href="betweenness_centrality.html"><tt>brandes_betweenness_centrality</tt></A></LI>
<li>Layout algorithms
<ol>
<li><a href="random_layout.html"><tt>random_graph_layout</tt></a></li>
<li><a href="circle_layout.html"><tt>circle_layout</tt></a></li>
<li><a href="kamada_kawai_spring_layout.html"><tt>kamada_kawai_spring_layout</tt></a></li>
<li><a href="fruchterman_reingold.html"><tt>fruchterman_reingold_force_directed_layout</tt></li>
</ol>
</li>
<li>Clustering algorithms
@ -193,6 +198,7 @@
<li><a href="bc_clustering.html"><tt>betweenness_centrality_clustering</tt></li>
</ol>
</li>
<li><a href="astar_search.html"><tt>astar_search</tt></li>
</OL>
</OL>

View File

@ -42,6 +42,7 @@ the following visitor concepts:
<li> <a href="./DFSVisitor.html">DFS Visitor</a>
<li> <a href="./DijkstraVisitor.html">Dijkstra Visitor</a>
<li> <a href="./BellmanFordVisitor.html">Bellman Ford Visitor</a>
<li> <a href="./AStarVisitor.html">A* Visitor</a>
<li> <a href="./EventVisitor.html">Event Visitor</a>
</ul>

224
example/astar-cities.cpp Normal file
View File

@ -0,0 +1,224 @@
//
//=======================================================================
// Copyright (c) 2004 Kristopher Beevers
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//
#include <boost/graph/astar_search.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/random.hpp>
#include <boost/random.hpp>
#include <boost/graph/graphviz.hpp>
#include <sys/time.h>
#include <vector>
#include <list>
#include <iostream>
#include <fstream>
#include <math.h> // for sqrt
using namespace boost;
using namespace std;
// auxiliary types
struct location
{
float y, x; // lat, long
};
typedef float cost;
template <class Name, class LocMap>
class city_writer {
public:
city_writer(Name n, LocMap l, float _minx, float _maxx,
float _miny, float _maxy,
unsigned int _ptx, unsigned int _pty)
: name(n), loc(l), minx(_minx), maxx(_maxx), miny(_miny),
maxy(_maxy), ptx(_ptx), pty(_pty) {}
template <class Vertex>
void operator()(ostream& out, const Vertex& v) const {
float px = 1 - (loc[v].x - minx) / (maxx - minx);
float py = (loc[v].y - miny) / (maxy - miny);
out << "[label=\"" << name[v] << "\", pos=\""
<< static_cast<unsigned int>(ptx * px) << ","
<< static_cast<unsigned int>(pty * py)
<< "\", fontsize=\"11\"]";
}
private:
Name name;
LocMap loc;
float minx, maxx, miny, maxy;
unsigned int ptx, pty;
};
template <class WeightMap>
class time_writer {
public:
time_writer(WeightMap w) : wm(w) {}
template <class Edge>
void operator()(ostream &out, const Edge& e) const {
out << "[label=\"" << wm[e] << "\", fontsize=\"11\"]";
}
private:
WeightMap wm;
};
// euclidean distance heuristic
template <class Graph, class CostType, class LocMap>
class distance_heuristic : public astar_heuristic<Graph, CostType>
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
distance_heuristic(LocMap l, Vertex goal)
: m_location(l), m_goal(goal) {}
CostType operator()(Vertex u)
{
CostType dx = m_location[m_goal].x - m_location[u].x;
CostType dy = m_location[m_goal].y - m_location[u].y;
return ::sqrt(dx * dx + dy * dy);
}
private:
LocMap m_location;
Vertex m_goal;
};
struct found_goal {}; // exception for termination
// visitor that terminates when we find the goal
template <class Vertex>
class astar_goal_visitor : public boost::default_astar_visitor
{
public:
astar_goal_visitor(Vertex goal) : m_goal(goal) {}
template <class Graph>
void examine_vertex(Vertex u, Graph& g) {
if(u == m_goal)
throw found_goal();
}
private:
Vertex m_goal;
};
int main(int argc, char **argv)
{
// specify some types
typedef adjacency_list<listS, vecS, undirectedS, no_property,
property<edge_weight_t, cost> > mygraph_t;
typedef property_map<mygraph_t, edge_weight_t>::type WeightMap;
typedef mygraph_t::vertex_descriptor vertex;
typedef mygraph_t::edge_descriptor edge_descriptor;
typedef mygraph_t::vertex_iterator vertex_iterator;
typedef std::pair<int, int> edge;
// specify data
enum nodes {
Troy, LakePlacid, Plattsburgh, Massena, Watertown, Utica,
Syracuse, Rochester, Buffalo, Ithaca, Binghamton, Woodstock,
NewYork, N
};
const char *name[] = {
"Troy", "Lake Placid", "Plattsburgh", "Massena",
"Watertown", "Utica", "Syracuse", "Rochester", "Buffalo",
"Ithaca", "Binghamton", "Woodstock", "New York"
};
location locations[] = { // lat/long
{42.73, 73.68}, {44.28, 73.99}, {44.70, 73.46},
{44.93, 74.89}, {43.97, 75.91}, {43.10, 75.23},
{43.04, 76.14}, {43.17, 77.61}, {42.89, 78.86},
{42.44, 76.50}, {42.10, 75.91}, {42.04, 74.11},
{40.67, 73.94}
};
edge edge_array[] = {
edge(Troy,Utica), edge(Troy,LakePlacid),
edge(Troy,Plattsburgh), edge(LakePlacid,Plattsburgh),
edge(Plattsburgh,Massena), edge(LakePlacid,Massena),
edge(Massena,Watertown), edge(Watertown,Utica),
edge(Watertown,Syracuse), edge(Utica,Syracuse),
edge(Syracuse,Rochester), edge(Rochester,Buffalo),
edge(Syracuse,Ithaca), edge(Ithaca,Binghamton),
edge(Ithaca,Rochester), edge(Binghamton,Troy),
edge(Binghamton,Woodstock), edge(Binghamton,NewYork),
edge(Syracuse,Binghamton), edge(Woodstock,Troy),
edge(Woodstock,NewYork)
};
unsigned int num_edges = sizeof(edge_array) / sizeof(edge);
cost weights[] = { // estimated travel time (mins)
96, 134, 143, 65, 115, 133, 117, 116, 74, 56,
84, 73, 69, 70, 116, 147, 173, 183, 74, 71, 124
};
// create graph
mygraph_t g(N);
WeightMap weightmap = get(edge_weight, g);
for(std::size_t j = 0; j < num_edges; ++j) {
edge_descriptor e; bool inserted;
tie(e, inserted) = add_edge(edge_array[j].first,
edge_array[j].second, g);
weightmap[e] = weights[j];
}
// pick random start/goal
mt19937 gen(time(0));
vertex start = random_vertex(g, gen);
vertex goal = random_vertex(g, gen);
cout << "Start vertex: " << name[start] << endl;
cout << "Goal vertex: " << name[goal] << endl;
ofstream dotfile;
dotfile.open("test-astar-cities.dot");
write_graphviz(dotfile, g,
city_writer<const char **, location*>
(name, locations, 73.46, 78.86, 40.67, 44.93,
480, 400),
time_writer<WeightMap>(weightmap));
vector<mygraph_t::vertex_descriptor> p(num_vertices(g));
vector<cost> d(num_vertices(g));
try {
// call astar named parameter interface
astar_search
(g, start,
distance_heuristic<mygraph_t, cost, location*>
(locations, goal),
predecessor_map(&p[0]).distance_map(&d[0]).
visitor(astar_goal_visitor<vertex>(goal)));
} catch(found_goal fg) { // found a path to the goal
list<vertex> shortest_path;
for(vertex v = goal;; v = p[v]) {
shortest_path.push_front(v);
if(p[v] == v)
break;
}
cout << "Shortest path from " << name[start] << " to "
<< name[goal] << ": ";
list<vertex>::iterator spi = shortest_path.begin();
cout << name[start];
for(++spi; spi != shortest_path.end(); ++spi)
cout << " -> " << name[*spi];
cout << endl << "Total travel time: " << d[goal] << endl;
return 0;
}
cout << "Didn't find a path from " << name[start] << "to"
<< name[goal] << "!" << endl;
return 0;
}

View File

@ -0,0 +1,36 @@
graph G {
0[label="Troy", pos="460,193", fontsize="11"];
1[label="Lake Placid", pos="432,338", fontsize="11"];
2[label="Plattsburgh", pos="480,378", fontsize="11"];
3[label="Massena", pos="352,400", fontsize="11"];
4[label="Watertown", pos="262,309", fontsize="11"];
5[label="Utica", pos="322,228", fontsize="11"];
6[label="Syracuse", pos="241,222", fontsize="11"];
7[label="Rochester", pos="111,234", fontsize="11"];
8[label="Buffalo", pos="0,208", fontsize="11"];
9[label="Ithaca", pos="209,166", fontsize="11"];
10[label="Binghamton", pos="262,134", fontsize="11"];
11[label="Woodstock", pos="422,128", fontsize="11"];
12[label="New York", pos="437,0", fontsize="11"];
0--5 [label="96", fontsize="11"];
0--1 [label="134", fontsize="11"];
0--2 [label="143", fontsize="11"];
1--2 [label="65", fontsize="11"];
2--3 [label="115", fontsize="11"];
1--3 [label="133", fontsize="11"];
3--4 [label="117", fontsize="11"];
4--5 [label="116", fontsize="11"];
4--6 [label="74", fontsize="11"];
5--6 [label="56", fontsize="11"];
6--7 [label="84", fontsize="11"];
7--8 [label="73", fontsize="11"];
6--9 [label="69", fontsize="11"];
9--10 [label="70", fontsize="11"];
9--7 [label="116", fontsize="11"];
10--0 [label="147", fontsize="11"];
10--11 [label="173", fontsize="11"];
10--12 [label="183", fontsize="11"];
6--10 [label="74", fontsize="11"];
11--0 [label="71", fontsize="11"];
11--12 [label="124", fontsize="11"];
}

View File

@ -0,0 +1,390 @@
//
//=======================================================================
// Copyright (c) 2004 Kristopher Beevers
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//
#ifndef BOOST_GRAPH_ASTAR_SEARCH_HPP
#define BOOST_GRAPH_ASTAR_SEARCH_HPP
#include <functional>
#include <boost/limits.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/pending/mutable_queue.hpp>
#include <boost/graph/relax.hpp>
#include <boost/pending/indirect_cmp.hpp>
#include <boost/graph/exception.hpp>
#include <boost/graph/breadth_first_search.hpp>
namespace boost {
template <class Heuristic, class Graph>
struct AStarHeuristicConcept {
void constraints()
{
function_requires< CopyConstructibleConcept<Heuristic> >();
h(u);
}
Heuristic h;
typename graph_traits<Graph>::vertex_descriptor u;
};
template <class Graph, class CostType>
class astar_heuristic : public std::unary_function<
typename graph_traits<Graph>::vertex_descriptor, CostType>
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
astar_heuristic() {}
CostType operator()(Vertex u) { return static_cast<CostType>(0); }
};
template <class Visitor, class Graph>
struct AStarVisitorConcept {
void constraints()
{
function_requires< CopyConstructibleConcept<Visitor> >();
vis.initialize_vertex(u, g);
vis.discover_vertex(u, g);
vis.examine_vertex(u, g);
vis.examine_edge(e, g);
vis.edge_relaxed(e, g);
vis.edge_not_relaxed(e, g);
vis.black_target(e, g);
vis.finish_vertex(u, g);
}
Visitor vis;
Graph g;
typename graph_traits<Graph>::vertex_descriptor u;
typename graph_traits<Graph>::edge_descriptor e;
};
template <class Visitors = null_visitor>
class astar_visitor : public bfs_visitor<Visitors> {
public:
astar_visitor() {}
astar_visitor(Visitors vis)
: bfs_visitor<Visitors>(vis) {}
template <class Edge, class Graph>
void edge_relaxed(Edge e, Graph& g) {
invoke_visitors(this->m_vis, e, g, on_edge_relaxed());
}
template <class Edge, class Graph>
void edge_not_relaxed(Edge e, Graph& g) {
invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed());
}
private:
template <class Edge, class Graph>
void tree_edge(Edge e, Graph& g) {}
template <class Edge, class Graph>
void non_tree_edge(Edge e, Graph& g) {}
};
template <class Visitors>
astar_visitor<Visitors>
make_astar_visitor(Visitors vis) {
return astar_visitor<Visitors>(vis);
}
typedef astar_visitor<> default_astar_visitor;
namespace detail {
template <class AStarHeuristic, class UniformCostVisitor,
class UpdatableQueue, class PredecessorMap,
class CostMap, class DistanceMap, class WeightMap,
class ColorMap, class BinaryFunction,
class BinaryPredicate>
struct astar_bfs_visitor
{
typedef typename property_traits<CostMap>::value_type C;
typedef typename property_traits<ColorMap>::value_type ColorValue;
typedef color_traits<ColorValue> Color;
astar_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis,
UpdatableQueue& Q, PredecessorMap p,
CostMap c, DistanceMap d, WeightMap w,
ColorMap col, BinaryFunction combine,
BinaryPredicate compare, C zero)
: m_h(h), m_vis(vis), m_Q(Q), m_predecessor(p), m_cost(c),
m_distance(d), m_weight(w), m_color(col),
m_combine(combine), m_compare(compare), m_zero(zero) {}
template <class Vertex, class Graph>
void initialize_vertex(Vertex u, Graph& g) {
m_vis.initialize_vertex(u, g);
}
template <class Vertex, class Graph>
void discover_vertex(Vertex u, Graph& g) {
m_vis.discover_vertex(u, g);
}
template <class Vertex, class Graph>
void examine_vertex(Vertex u, Graph& g) {
m_vis.examine_vertex(u, g);
}
template <class Vertex, class Graph>
void finish_vertex(Vertex u, Graph& g) {
m_vis.finish_vertex(u, g);
}
template <class Edge, class Graph>
void examine_edge(Edge e, Graph& g) {
if (m_compare(get(m_weight, e), m_zero))
throw negative_edge();
m_vis.examine_edge(e, g);
}
template <class Edge, class Graph>
void non_tree_edge(Edge, Graph&) {}
template <class Edge, class Graph>
void tree_edge(Edge e, Graph& g) {
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if(m_decreased) {
m_vis.edge_relaxed(e, g);
put(m_cost, target(e, g),
m_combine(get(m_distance, target(e, g)),
m_h(target(e, g))));
} else
m_vis.edge_not_relaxed(e, g);
}
template <class Edge, class Graph>
void gray_target(Edge e, Graph& g) {
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if(m_decreased) {
put(m_cost, target(e, g),
m_combine(get(m_distance, target(e, g)),
m_h(target(e, g))));
m_Q.update(target(e, g));
m_vis.edge_relaxed(e, g);
} else
m_vis.edge_not_relaxed(e, g);
}
template <class Edge, class Graph>
void black_target(Edge e, Graph& g) {
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if(m_decreased) {
m_vis.edge_relaxed(e, g);
put(m_cost, target(e, g),
m_combine(get(m_distance, target(e, g)),
m_h(target(e, g))));
m_Q.push(target(e, g));
put(m_color, target(e, g), Color::gray());
m_vis.black_target(e, g);
} else
m_vis.edge_not_relaxed(e, g);
}
AStarHeuristic m_h;
UniformCostVisitor m_vis;
UpdatableQueue& m_Q;
PredecessorMap m_predecessor;
CostMap m_cost;
DistanceMap m_distance;
WeightMap m_weight;
ColorMap m_color;
BinaryFunction m_combine;
BinaryPredicate m_compare;
bool m_decreased;
C m_zero;
};
} // namespace detail
template <typename VertexListGraph, typename AStarHeuristic,
typename AStarVisitor, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap, typename ColorMap,
typename VertexIndexMap,
typename CompareFunction, typename CombineFunction,
typename CostInf, typename CostZero>
inline void
astar_search_no_init
(VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
ColorMap color, VertexIndexMap index_map,
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero)
{
typedef indirect_cmp<CostMap, CompareFunction> IndirectCmp;
IndirectCmp icmp(cost, compare);
typedef typename graph_traits<VertexListGraph>::vertex_descriptor
Vertex;
typedef mutable_queue<Vertex, std::vector<Vertex>,
IndirectCmp, VertexIndexMap>
MutableQueue;
MutableQueue Q(num_vertices(g), icmp, index_map);
detail::astar_bfs_visitor<AStarHeuristic, AStarVisitor,
MutableQueue, PredecessorMap, CostMap, DistanceMap,
WeightMap, ColorMap, CombineFunction, CompareFunction>
bfs_vis(h, vis, Q, predecessor, cost, distance, weight,
color, combine, compare, zero);
breadth_first_visit(g, s, Q, bfs_vis, color);
}
// Non-named parameter interface
template <typename VertexListGraph, typename AStarHeuristic,
typename AStarVisitor, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap, typename VertexIndexMap,
typename ColorMap,
typename CompareFunction, typename CombineFunction,
typename CostInf, typename CostZero>
inline void
astar_search
(VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
VertexIndexMap index_map, ColorMap color,
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero)
{
typedef typename property_traits<ColorMap>::value_type ColorValue;
typedef color_traits<ColorValue> Color;
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
for (tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
put(color, *ui, Color::white());
put(distance, *ui, inf);
put(cost, *ui, inf);
put(predecessor, *ui, *ui);
}
put(distance, s, zero);
put(cost, s, h(s));
astar_search_no_init
(g, s, h, vis, predecessor, cost, distance, weight,
color, index_map, compare, combine, inf, zero);
}
namespace detail {
template <class VertexListGraph, class AStarHeuristic,
class CostMap, class DistanceMap, class WeightMap,
class IndexMap, class ColorMap, class Params>
inline void
astar_dispatch2
(VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, CostMap cost, DistanceMap distance,
WeightMap weight, IndexMap index_map, ColorMap color,
const Params& params)
{
dummy_property_map p_map;
typedef typename property_traits<CostMap>::value_type C;
astar_search
(g, s, h,
choose_param(get_param(params, graph_visitor),
make_astar_visitor(null_visitor())),
choose_param(get_param(params, vertex_predecessor), p_map),
cost, distance, weight, index_map, color,
choose_param(get_param(params, distance_compare_t()),
std::less<C>()),
choose_param(get_param(params, distance_combine_t()),
closed_plus<C>()),
choose_param(get_param(params, distance_inf_t()),
std::numeric_limits<C>::max()),
choose_param(get_param(params, distance_zero_t()),
C()));
}
template <class VertexListGraph, class AStarHeuristic,
class CostMap, class DistanceMap, class WeightMap,
class IndexMap, class ColorMap, class Params>
inline void
astar_dispatch1
(VertexListGraph& g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, CostMap cost, DistanceMap distance,
WeightMap weight, IndexMap index_map, ColorMap color,
const Params& params)
{
typedef typename property_traits<WeightMap>::value_type D;
typename std::vector<D>::size_type
n = is_default_param(distance) ? num_vertices(g) : 1;
std::vector<D> distance_map(n);
n = is_default_param(cost) ? num_vertices(g) : 1;
std::vector<D> cost_map(n);
std::vector<default_color_type> color_map(num_vertices(g));
default_color_type c = white_color;
detail::astar_dispatch2
(g, s, h,
choose_param(cost, make_iterator_property_map
(cost_map.begin(), index_map,
cost_map[0])),
choose_param(distance, make_iterator_property_map
(distance_map.begin(), index_map,
distance_map[0])),
weight, index_map,
choose_param(color, make_iterator_property_map
(color_map.begin(), index_map, c)),
params);
}
} // namespace detail
// Named parameter interface
template <typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R>
void
astar_search
(VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, const bgl_named_params<P, T, R>& params)
{
detail::astar_dispatch1
(g, s, h,
get_param(params, vertex_rank),
get_param(params, vertex_distance),
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
choose_const_pmap(get_param(params, vertex_index), g, vertex_index),
get_param(params, vertex_color),
params);
}
} // namespace boost
#endif // BOOST_GRAPH_ASTAR_SEARCH_HPP

View File

@ -120,6 +120,8 @@ namespace boost {
typedef typename property_traits<DistanceMap>::value_type D_value;
typedef typename property_traits<WeightMap>::value_type W_value;
D_value inf = (std::numeric_limits<D_value>::max)();
typename GTraits::edge_iterator i, end;
for (Size k = 0; k < N; ++k) {
@ -137,8 +139,8 @@ namespace boost {
}
for (tie(i, end) = edges(g); i != end; ++i)
if (compare(combine(get(distance, source(*i, g)),
get(weight, *i)),
if (compare(inf_combine(get(distance, source(*i, g)),
get(weight, *i), inf, combine, compare),
get(distance, target(*i,g))))
{
v.edge_not_minimized(*i, g);

View File

@ -0,0 +1,240 @@
// Copyright 2002 Rensselaer Polytechnic Institute
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Lauren Foutz
// Scott Hill
/*
This file implements the functions
template <class VertexListGraph, class DistanceMatrix,
class P, class T, class R>
bool floyd_warshall_initialized_all_pairs_shortest_paths(
const VertexListGraph& g, DistanceMatrix& d,
const bgl_named_params<P, T, R>& params)
AND
template <class VertexAndEdgeListGraph, class DistanceMatrix,
class P, class T, class R>
bool floyd_warshall_all_pairs_shortest_paths(
const VertexAndEdgeListGraph& g, DistanceMatrix& d,
const bgl_named_params<P, T, R>& params)
*/
#ifndef BOOST_GRAPH_FLOYD_WARSHALL_HPP
#define BOOST_GRAPH_FLOYD_WARSHALL_HPP
#include <boost/property_map.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/relax.hpp>
namespace boost
{
template <typename VertexListGraph, typename DistanceMatrix,
typename BinaryPredicate, typename BinaryFunction,
typename Infinity, typename Zero>
bool floyd_warshall_initialized_all_pairs_shortest_paths(
const VertexListGraph& g, DistanceMatrix& d,
const BinaryPredicate& compare,
const BinaryFunction& combine, const Infinity& inf,
const Zero& zero)
{
function_requires<VertexListGraphConcept<VertexListGraph> >();
return detail::floyd_warshall_dispatch(g, d, compare, combine,
inf, zero);
}
template <typename VertexAndEdgeListGraph, typename DistanceMatrix,
typename WeightMap, typename BinaryPredicate,
typename BinaryFunction, typename Infinity, typename Zero>
bool floyd_warshall_all_pairs_shortest_paths(
const VertexAndEdgeListGraph& g,
DistanceMatrix& d, const WeightMap& w,
const BinaryPredicate& compare, const BinaryFunction& combine,
const Infinity& inf, const Zero& zero)
{
function_requires<VertexListGraphConcept<VertexAndEdgeListGraph> >();
function_requires<EdgeListGraphConcept<VertexAndEdgeListGraph> >();
function_requires<IncidenceGraphConcept<VertexAndEdgeListGraph> >();
typename graph_traits<VertexAndEdgeListGraph>::vertex_iterator
firstv, lastv, firstv2, lastv2;
typename graph_traits<VertexAndEdgeListGraph>::edge_iterator first, last;
for(tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++)
for(tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2; firstv2++)
d[*firstv][*firstv2] = inf;
for(tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++)
d[*firstv][*firstv] = 0;
for(tie(first, last) = edges(g); first != last; first++)
{
if (d[source(*first, g)][target(*first, g)] != inf)
d[source(*first, g)][target(*first, g)] =
std::min(get(w, *first),
d[source(*first, g)][target(*first, g)]);
else
d[source(*first, g)][target(*first, g)] = get(w, *first);
}
bool is_undirected = is_same<typename
graph_traits<VertexAndEdgeListGraph>::directed_category,
undirected_tag>::value;
if (is_undirected)
{
for(tie(first, last) = edges(g); first != last; first++)
{
if (d[target(*first, g)][source(*first, g)] != inf)
d[target(*first, g)][source(*first, g)] =
std::min(get(w, *first),
d[target(*first, g)][source(*first, g)]);
else
d[target(*first, g)][source(*first, g)] = get(w, *first);
}
}
return detail::floyd_warshall_dispatch(g, d, compare, combine,
inf, zero);
}
namespace detail {
template<typename VertexListGraph, typename DistanceMatrix,
typename BinaryPredicate, typename BinaryFunction,
typename Infinity, typename Zero>
bool floyd_warshall_dispatch(const VertexListGraph& g,
DistanceMatrix& d, const BinaryPredicate &compare,
const BinaryFunction &combine, const Infinity& inf,
const Zero& zero)
{
typename graph_traits<VertexListGraph>::vertex_iterator
i, lasti, j, lastj, k, lastk;
for (tie(k, lastk) = vertices(g); k != lastk; k++)
for (tie(i, lasti) = vertices(g); i != lasti; i++)
for (tie(j, lastj) = vertices(g); j != lastj; j++)
{
d[*i][*j] = std::min(d[*i][*j],
inf_combine(d[*i][*k], d[*k][*j], inf, combine,
compare), compare);
}
for (tie(i, lasti) = vertices(g); i != lasti; i++)
if (compare(d[*i][*i], zero))
return false;
return true;
}
template <class VertexListGraph, class DistanceMatrix,
class WeightMap, class P, class T, class R>
bool floyd_warshall_init_dispatch(const VertexListGraph& g,
DistanceMatrix& d, WeightMap w,
const bgl_named_params<P, T, R>& params)
{
typedef typename property_traits<WeightMap>::value_type WM;
return floyd_warshall_initialized_all_pairs_shortest_paths(g, d,
choose_param(get_param(params, distance_compare_t()),
std::less<WM>()),
choose_param(get_param(params, distance_combine_t()),
std::plus<WM>()),
choose_param(get_param(params, distance_inf_t()),
std::numeric_limits<WM>::max()),
choose_param(get_param(params, distance_zero_t()),
WM()));
}
template <class VertexAndEdgeListGraph, class DistanceMatrix,
class WeightMap, class P, class T, class R>
bool floyd_warshall_noninit_dispatch(const VertexAndEdgeListGraph& g,
DistanceMatrix& d, WeightMap w,
const bgl_named_params<P, T, R>& params)
{
typedef typename property_traits<WeightMap>::value_type WM;
return floyd_warshall_all_pairs_shortest_paths(g, d, w,
choose_param(get_param(params, distance_compare_t()),
std::less<WM>()),
choose_param(get_param(params, distance_combine_t()),
std::plus<WM>()),
choose_param(get_param(params, distance_inf_t()),
std::numeric_limits<WM>::max()),
choose_param(get_param(params, distance_zero_t()),
WM()));
}
} // namespace detail
template <class VertexListGraph, class DistanceMatrix, class P,
class T, class R>
bool floyd_warshall_initialized_all_pairs_shortest_paths(
const VertexListGraph& g, DistanceMatrix& d,
const bgl_named_params<P, T, R>& params)
{
return detail::floyd_warshall_init_dispatch(g, d,
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
params);
}
template <class VertexListGraph, class DistanceMatrix>
bool floyd_warshall_initialized_all_pairs_shortest_paths(
const VertexListGraph& g, DistanceMatrix& d)
{
bgl_named_params<int,int> params(0);
return detail::floyd_warshall_init_dispatch(g, d,
get(edge_weight, g), params);
}
template <class VertexAndEdgeListGraph, class DistanceMatrix,
class P, class T, class R>
bool floyd_warshall_all_pairs_shortest_paths(
const VertexAndEdgeListGraph& g, DistanceMatrix& d,
const bgl_named_params<P, T, R>& params)
{
return detail::floyd_warshall_noninit_dispatch(g, d,
choose_const_pmap(get_param(params, edge_weight), g, edge_weight),
params);
}
template <class VertexAndEdgeListGraph, class DistanceMatrix>
bool floyd_warshall_all_pairs_shortest_paths(
const VertexAndEdgeListGraph& g, DistanceMatrix& d)
{
bgl_named_params<int,int> params(0);
return detail::floyd_warshall_noninit_dispatch(g, d,
get(edge_weight, g), params);
}
} // namespace boost
#endif

View File

@ -0,0 +1,378 @@
// Copyright 2004 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#ifndef BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
#define BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP
#include <cmath>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/named_function_params.hpp>
#include <boost/graph/simple_point.hpp>
#include <vector>
#include <list>
namespace boost {
struct square_distance_attractive_force {
template<typename Graph, typename T>
T
operator()(typename graph_traits<Graph>::edge_descriptor,
T k,
T d,
const Graph&) const
{
return d * d / k;
}
};
struct square_distance_repulsive_force {
template<typename Graph, typename T>
T
operator()(typename graph_traits<Graph>::vertex_descriptor,
typename graph_traits<Graph>::vertex_descriptor,
T k,
T d,
const Graph&) const
{
return k * k / d;
}
};
template<typename T>
struct linear_cooling {
typedef T result_type;
linear_cooling(std::size_t iterations)
: temp(T(iterations) / T(10)), step(0.1) { }
linear_cooling(std::size_t iterations, T temp)
: temp(temp), step(temp / T(iterations)) { }
T operator()()
{
T old_temp = temp;
temp -= step;
if (temp < T(0)) temp = T(0);
return old_temp;
}
private:
T temp;
T step;
};
struct all_force_pairs
{
template<typename Graph, typename ApplyForce >
void operator()(const Graph& g, ApplyForce apply_force)
{
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
vertex_iterator v, end;
for (tie(v, end) = vertices(g); v != end; ++v) {
vertex_iterator u = v;
for (++u; u != end; ++u) {
apply_force(*u, *v);
apply_force(*v, *u);
}
}
}
};
template<typename Dim, typename PositionMap>
struct grid_force_pairs
{
explicit grid_force_pairs(Dim width, Dim height, PositionMap position)
: width(width), height(height), position(position)
{
using std::sqrt;
two_k = Dim(2) * sqrt(width*height);
}
template<typename Graph, typename ApplyForce >
void operator()(const Graph& g, ApplyForce apply_force)
{
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef std::list<vertex_descriptor> bucket_t;
typedef std::vector<bucket_t> buckets_t;
std::size_t columns = std::size_t(width / two_k);
buckets_t buckets(num_vertices(g) / 4);
vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
std::size_t column = std::size_t((position[*v].x - width / 2) / two_k);
std::size_t row = std::size_t((position[*v].y - height / 2) / two_k);
buckets.at(row * columns + column).push_back(*v);
}
typedef typename buckets_t::iterator buckets_iterator;
for (buckets_iterator i = buckets.begin(); i != buckets.end(); ++i) {
typedef typename bucket_t::iterator bucket_iterator;
for (bucket_iterator u = i->begin(); u != i->end(); ++u) {
for (bucket_iterator v = i->begin(); v != i->end(); ++v) {
if (*u != *v) apply_force(*u, *v);
}
}
}
}
private:
Dim width;
Dim height;
PositionMap position;
Dim two_k;
};
template<typename Dim, typename PositionMap>
inline grid_force_pairs<Dim, PositionMap>
make_grid_force_pairs(Dim width, Dim height, const PositionMap& position)
{ return grid_force_pairs<Dim, PositionMap>(width, height, position); }
template<typename Graph, typename PositionMap, typename Dim>
void
scale_graph(const Graph& g, PositionMap position,
Dim left, Dim top, Dim right, Dim bottom)
{
if (num_vertices(g) == 0) return;
if (bottom > top) {
using std::swap;
swap(bottom, top);
}
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
// Find min/max ranges
Dim minX = position[*vertices(g).first].x, maxX = minX;
Dim minY = position[*vertices(g).first].y, maxY = minY;
vertex_iterator vi, vi_end;
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
using std::min; // TBD: eric's tricks
using std::max;
minX = min(minX, position[*vi].x);
maxX = max(maxX, position[*vi].x);
minY = min(minY, position[*vi].y);
maxY = max(maxY, position[*vi].y);
}
// Scale to bounding box provided
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
position[*vi].x = ((position[*vi].x - minX) / (maxX - minX))
* (right - left) + left;
position[*vi].y = ((position[*vi].y - minY) / (maxY - minY))
* (top - bottom) + bottom;
}
}
namespace detail {
template<typename PositionMap, typename DisplacementMap,
typename RepulsiveForce, typename Dim, typename Graph>
struct fr_apply_force
{
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
fr_apply_force(const PositionMap& position,
const DisplacementMap& displacement,
RepulsiveForce repulsive_force, Dim k, const Graph& g)
: position(position), displacement(displacement),
repulsive_force(repulsive_force), k(k), g(g)
{ }
void operator()(vertex_descriptor u, vertex_descriptor v)
{
if (u != v) {
using std::sqrt;
Dim delta_x = position[v].x - position[u].x;
Dim delta_y = position[v].y - position[u].y;
Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y);
Dim fr = repulsive_force(u, v, k, dist, g);
displacement[v].x += delta_x / dist * fr;
displacement[v].y += delta_y / dist * fr;
}
}
private:
PositionMap position;
DisplacementMap displacement;
RepulsiveForce repulsive_force;
Dim k;
const Graph& g;
};
} // end namespace detail
template<typename Graph, typename PositionMap, typename Dim,
typename AttractiveForce, typename RepulsiveForce,
typename ForcePairs, typename Cooling, typename DisplacementMap>
void
fruchterman_reingold_force_directed_layout
(const Graph& g,
PositionMap position,
Dim width,
Dim height,
AttractiveForce attractive_force,
RepulsiveForce repulsive_force,
ForcePairs force_pairs,
Cooling cool,
DisplacementMap displacement)
{
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
using std::sqrt;
Dim area = width * height;
// assume positions are initialized randomly
Dim k = sqrt(area / num_vertices(g));
detail::fr_apply_force<PositionMap, DisplacementMap,
RepulsiveForce, Dim, Graph>
apply_force(position, displacement, repulsive_force, k, g);
while (Dim temp = cool()) {
// Calculate repulsive forces
vertex_iterator v, v_end;
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
displacement[*v].x = 0;
displacement[*v].y = 0;
}
force_pairs(g, apply_force);
// Calculate attractive forces
edge_iterator e, e_end;
for (tie(e, e_end) = edges(g); e != e_end; ++e) {
vertex_descriptor v = source(*e, g);
vertex_descriptor u = target(*e, g);
Dim delta_x = position[v].x - position[u].x;
Dim delta_y = position[v].y - position[u].y;
Dim dist = sqrt(delta_x * delta_x + delta_y * delta_y);
Dim fa = attractive_force(*e, k, dist, g);
displacement[v].x -= delta_x / dist * fa;
displacement[v].y -= delta_y / dist * fa;
displacement[u].x += delta_x / dist * fa;
displacement[u].y += delta_y / dist * fa;
}
// Update positions
for (tie(v, v_end) = vertices(g); v != v_end; ++v) {
using std::min; // TBD: use Eric's crazy hacks here
using std::max; // TBD: use Eric's crazy hacks here
Dim disp_size = sqrt(displacement[*v].x * displacement[*v].x
+ displacement[*v].y * displacement[*v].y);
position[*v].x += displacement[*v].x / disp_size * min(disp_size, temp);
position[*v].y += displacement[*v].y / disp_size * min(disp_size, temp);
position[*v].x = min(width / 2, max(-width / 2, position[*v].x));
position[*v].y = min(height / 2, max(-height / 2, position[*v].y));
}
}
}
namespace detail {
template<typename DisplacementMap>
struct fr_force_directed_layout
{
template<typename Graph, typename PositionMap, typename Dim,
typename AttractiveForce, typename RepulsiveForce,
typename ForcePairs, typename Cooling,
typename Param, typename Tag, typename Rest>
static void
run(const Graph& g,
PositionMap position,
Dim width,
Dim height,
AttractiveForce attractive_force,
RepulsiveForce repulsive_force,
ForcePairs force_pairs,
Cooling cool,
DisplacementMap displacement,
const bgl_named_params<Param, Tag, Rest>&)
{
fruchterman_reingold_force_directed_layout
(g, position, width, height, attractive_force, repulsive_force,
force_pairs, cool, displacement);
}
};
template<>
struct fr_force_directed_layout<error_property_not_found>
{
template<typename Graph, typename PositionMap, typename Dim,
typename AttractiveForce, typename RepulsiveForce,
typename ForcePairs, typename Cooling,
typename Param, typename Tag, typename Rest>
static void
run(const Graph& g,
PositionMap position,
Dim width,
Dim height,
AttractiveForce attractive_force,
RepulsiveForce repulsive_force,
ForcePairs force_pairs,
Cooling cool,
error_property_not_found,
const bgl_named_params<Param, Tag, Rest>& params)
{
std::vector<simple_point<double> > displacements(num_vertices(g));
fruchterman_reingold_force_directed_layout
(g, position, width, height, attractive_force, repulsive_force,
force_pairs, cool,
make_iterator_property_map
(displacements.begin(),
choose_const_pmap(get_param(params, vertex_index), g,
vertex_index)));
}
};
} // end namespace detail
template<typename Graph, typename PositionMap, typename Dim, typename Param,
typename Tag, typename Rest>
void
fruchterman_reingold_force_directed_layout
(const Graph& g,
PositionMap position,
Dim width,
Dim height,
const bgl_named_params<Param, Tag, Rest>& params)
{
typedef typename property_value<bgl_named_params<Param,Tag,Rest>,
vertex_displacement_t>::type D;
detail::fr_force_directed_layout<D>::run
(g, position, width, height,
choose_param(get_param(params, attractive_force_t()),
square_distance_attractive_force()),
choose_param(get_param(params, repulsive_force_t()),
square_distance_repulsive_force()),
choose_param(get_param(params, force_pairs_t()),
make_grid_force_pairs(width, height, position)),
choose_param(get_param(params, cooling_t()),
linear_cooling<double>(100)),
get_param(params, vertex_displacement_t()),
params);
}
template<typename Graph, typename PositionMap, typename Dim, typename Param,
typename Tag, typename Rest>
void
fruchterman_reingold_force_directed_layout(const Graph& g,
PositionMap position,
Dim width,
Dim height)
{
fruchterman_reingold_force_directed_layout
(g, position, width, height,
attractive_force(square_distance_attractive_force()));
}
} // end namespace boost
#endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP

View File

@ -45,6 +45,11 @@ namespace boost {
struct vertex_max_invariant_t { };
struct orig_to_copy_t { };
struct root_vertex_t { };
struct attractive_force_t { };
struct repulsive_force_t { };
struct force_pairs_t { };
struct cooling_t { };
struct vertex_displacement_t { };
namespace detail {
template <class T>
@ -284,6 +289,42 @@ namespace boost {
return Params(c, *this);
}
template <typename VertexDisplacement>
bgl_named_params<VertexDisplacement, vertex_displacement_t, self>
displacement_map(const VertexDisplacement& c) const {
typedef bgl_named_params<VertexDisplacement, vertex_displacement_t, self> Params;
return Params(c, *this);
}
template <typename AttractiveForce>
bgl_named_params<AttractiveForce, attractive_force_t, self>
attractive_force(const AttractiveForce& c) {
typedef bgl_named_params<AttractiveForce, attractive_force_t, self> Params;
return Params(c, *this);
}
template <typename RepulsiveForce>
bgl_named_params<RepulsiveForce, repulsive_force_t, self>
repulsive_force(const RepulsiveForce& c) {
typedef bgl_named_params<RepulsiveForce, repulsive_force_t, self> Params;
return Params(c, *this);
}
template <typename ForcePairs>
bgl_named_params<ForcePairs, force_pairs_t, self>
force_pairs(const ForcePairs& c) {
typedef bgl_named_params<ForcePairs, force_pairs_t, self> Params;
return Params(c, *this);
}
template <typename Cooling>
bgl_named_params<Cooling, cooling_t, self>
cooling(const Cooling& c) {
typedef bgl_named_params<Cooling, cooling_t, self> Params;
return Params(c, *this);
}
};
template <typename WeightMap>
@ -484,6 +525,41 @@ namespace boost {
return Params(c);
}
template <typename VertexDisplacement>
bgl_named_params<VertexDisplacement, vertex_displacement_t>
displacement_map(const VertexDisplacement& c) {
typedef bgl_named_params<VertexDisplacement, vertex_displacement_t> Params;
return Params(c);
}
template <typename AttractiveForce>
bgl_named_params<AttractiveForce, attractive_force_t>
attractive_force(const AttractiveForce& c) {
typedef bgl_named_params<AttractiveForce, attractive_force_t> Params;
return Params(c);
}
template <typename RepulsiveForce>
bgl_named_params<RepulsiveForce, repulsive_force_t>
repulsive_force(const RepulsiveForce& c) {
typedef bgl_named_params<RepulsiveForce, repulsive_force_t> Params;
return Params(c);
}
template <typename ForcePairs>
bgl_named_params<ForcePairs, force_pairs_t>
force_pairs(const ForcePairs& c) {
typedef bgl_named_params<ForcePairs, force_pairs_t> Params;
return Params(c);
}
template <typename Cooling>
bgl_named_params<Cooling, cooling_t>
cooling(const Cooling& c) {
typedef bgl_named_params<Cooling, cooling_t> Params;
return Params(c);
}
//===========================================================================
// Functions for extracting parameters from bgl_named_params

View File

@ -0,0 +1,49 @@
// Copyright 2004 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#ifndef BOOST_GRAPH_RANDOM_LAYOUT_HPP
#define BOOST_GRAPH_RANDOM_LAYOUT_HPP
#include <boost/graph/graph_traits.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/mpl/if.hpp>
namespace boost {
template<typename Graph, typename PositionMap, typename Dimension,
typename RandomNumberGenerator>
void
random_graph_layout(const Graph& g, PositionMap position_map,
Dimension minX, Dimension maxX,
Dimension minY, Dimension maxY,
RandomNumberGenerator& gen)
{
typedef typename mpl::if_<is_integral<Dimension>,
uniform_int<Dimension>,
uniform_real<Dimension> >::type distrib_t;
typedef typename mpl::if_<is_integral<Dimension>,
RandomNumberGenerator&,
uniform_01<RandomNumberGenerator, Dimension> >
::type gen_t;
gen_t my_gen(gen);
distrib_t x(minX, maxX);
distrib_t y(minY, maxY);
typename graph_traits<Graph>::vertex_iterator vi, vi_end;
for(tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) {
position_map[*vi].x = x(my_gen);
position_map[*vi].y = y(my_gen);
}
}
} // end namespace boost
#endif // BOOST_GRAPH_RANDOM_LAYOUT_HPP

View File

@ -1,6 +1,8 @@
//
//=======================================================================
// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
// Copyright 2002 Rensselaer Polytechnic Institute
//
// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
//
// This file is part of the Boost Graph Library
@ -25,6 +27,15 @@
//=======================================================================
//
// Copyright 2002 Rensselaer Polytechnic Institute
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Lauren Foutz
// Scott Hill
#ifndef BOOST_GRAPH_RELAX_HPP
#define BOOST_GRAPH_RELAX_HPP
@ -35,6 +46,18 @@
namespace boost {
template<typename MatrixValue, typename BinaryFunction,
typename BinaryPredicate>
inline MatrixValue inf_combine(MatrixValue a, MatrixValue b,
MatrixValue inf, BinaryFunction combine,
BinaryPredicate compare)
{
if(compare(a, inf) && compare(b, inf))
return combine(a, b);
else
return inf;
}
// The following version of the plus functor prevents
// problems due to overflow at positive infinity.
@ -70,13 +93,15 @@ namespace boost {
typedef typename property_traits<WeightMap>::value_type W;
D d_u = get(d, u), d_v = get(d, v);
W w_e = get(w, e);
if ( compare(combine(d_u, w_e), d_v) ) {
put(d, v, combine(d_u, w_e));
D inf = (std::numeric_limits<D>::max)();
if ( compare(inf_combine(d_u, w_e, inf, combine, compare), d_v) ) {
put(d, v, inf_combine(d_u, w_e, inf, combine, compare));
put(p, v, u);
return true;
} else if (is_undirected && compare(combine(d_v, w_e), d_u)) {
put(d, u, combine(d_v, w_e));
} else if (is_undirected
&& compare(inf_combine(d_v, w_e, inf, combine, compare), d_u)) {
put(d, u, inf_combine(d_v, w_e, inf, combine, compare));
put(p, u, v);
return true;
} else

View File

@ -0,0 +1,15 @@
#ifndef BOOST_GRAPH_SIMPLE_POINT_HPP
#define BOOST_GRAPH_SIMPLE_POINT_HPP
namespace boost {
template<typename T>
struct simple_point
{
T x;
T y;
};
} // end namespace boost
#endif // BOOST_GRAPH_SIMPLE_POINT_HPP

View File

@ -58,6 +58,9 @@ test-suite graph :
[ run bundled_properties.cpp ]
[ run floyd_warshall_test.cpp ]
[ run astar_search_test.cpp ]
;
# Run SDB tests only when -sSDB= is set.

213
test/astar_search_test.cpp Normal file
View File

@ -0,0 +1,213 @@
//
//=======================================================================
// Copyright (c) 2004 Kristopher Beevers
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
//=======================================================================
//
#include <boost/graph/astar_search.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/random.hpp>
#include <boost/random.hpp>
#include <sys/time.h>
#include <vector>
#include <list>
#include <iostream>
#include <math.h> // for sqrt
using namespace boost;
using namespace std;
// auxiliary types
struct location
{
float y, x; // lat, long
};
typedef float cost;
template <class Name, class LocMap>
class city_writer {
public:
city_writer(Name n, LocMap l, float _minx, float _maxx,
float _miny, float _maxy,
unsigned int _ptx, unsigned int _pty)
: name(n), loc(l), minx(_minx), maxx(_maxx), miny(_miny),
maxy(_maxy), ptx(_ptx), pty(_pty) {}
template <class Vertex>
void operator()(ostream& out, const Vertex& v) const {
float px = 1 - (loc[v].x - minx) / (maxx - minx);
float py = (loc[v].y - miny) / (maxy - miny);
out << "[label=\"" << name[v] << "\", pos=\""
<< static_cast<unsigned int>(ptx * px) << ","
<< static_cast<unsigned int>(pty * py)
<< "\", fontsize=\"11\"]";
}
private:
Name name;
LocMap loc;
float minx, maxx, miny, maxy;
unsigned int ptx, pty;
};
template <class WeightMap>
class time_writer {
public:
time_writer(WeightMap w) : wm(w) {}
template <class Edge>
void operator()(ostream &out, const Edge& e) const {
out << "[label=\"" << wm[e] << "\", fontsize=\"11\"]";
}
private:
WeightMap wm;
};
// euclidean distance heuristic
template <class Graph, class CostType, class LocMap>
class distance_heuristic : public astar_heuristic<Graph, CostType>
{
public:
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
distance_heuristic(LocMap l, Vertex goal)
: m_location(l), m_goal(goal) {}
CostType operator()(Vertex u)
{
CostType dx = m_location[m_goal].x - m_location[u].x;
CostType dy = m_location[m_goal].y - m_location[u].y;
return ::sqrt(dx * dx + dy * dy);
}
private:
LocMap m_location;
Vertex m_goal;
};
struct found_goal {}; // exception for termination
// visitor that terminates when we find the goal
template <class Vertex>
class astar_goal_visitor : public boost::default_astar_visitor
{
public:
astar_goal_visitor(Vertex goal) : m_goal(goal) {}
template <class Graph>
void examine_vertex(Vertex u, Graph& g) {
if(u == m_goal)
throw found_goal();
}
private:
Vertex m_goal;
};
int main(int argc, char **argv)
{
// specify some types
typedef adjacency_list<listS, vecS, undirectedS, no_property,
property<edge_weight_t, cost> > mygraph_t;
typedef property_map<mygraph_t, edge_weight_t>::type WeightMap;
typedef mygraph_t::vertex_descriptor vertex;
typedef mygraph_t::edge_descriptor edge_descriptor;
typedef mygraph_t::vertex_iterator vertex_iterator;
typedef std::pair<int, int> edge;
// specify data
enum nodes {
Troy, LakePlacid, Plattsburgh, Massena, Watertown, Utica,
Syracuse, Rochester, Buffalo, Ithaca, Binghamton, Woodstock,
NewYork, N
};
const char *name[] = {
"Troy", "Lake Placid", "Plattsburgh", "Massena",
"Watertown", "Utica", "Syracuse", "Rochester", "Buffalo",
"Ithaca", "Binghamton", "Woodstock", "New York"
};
location locations[] = { // lat/long
{42.73, 73.68}, {44.28, 73.99}, {44.70, 73.46},
{44.93, 74.89}, {43.97, 75.91}, {43.10, 75.23},
{43.04, 76.14}, {43.17, 77.61}, {42.89, 78.86},
{42.44, 76.50}, {42.10, 75.91}, {42.04, 74.11},
{40.67, 73.94}
};
edge edge_array[] = {
edge(Troy,Utica), edge(Troy,LakePlacid),
edge(Troy,Plattsburgh), edge(LakePlacid,Plattsburgh),
edge(Plattsburgh,Massena), edge(LakePlacid,Massena),
edge(Massena,Watertown), edge(Watertown,Utica),
edge(Watertown,Syracuse), edge(Utica,Syracuse),
edge(Syracuse,Rochester), edge(Rochester,Buffalo),
edge(Syracuse,Ithaca), edge(Ithaca,Binghamton),
edge(Ithaca,Rochester), edge(Binghamton,Troy),
edge(Binghamton,Woodstock), edge(Binghamton,NewYork),
edge(Syracuse,Binghamton), edge(Woodstock,Troy),
edge(Woodstock,NewYork)
};
unsigned int num_edges = sizeof(edge_array) / sizeof(edge);
cost weights[] = { // estimated travel time (mins)
96, 134, 143, 65, 115, 133, 117, 116, 74, 56,
84, 73, 69, 70, 116, 147, 173, 183, 74, 71, 124
};
// create graph
mygraph_t g(N);
WeightMap weightmap = get(edge_weight, g);
for(std::size_t j = 0; j < num_edges; ++j) {
edge_descriptor e; bool inserted;
tie(e, inserted) = add_edge(edge_array[j].first,
edge_array[j].second, g);
weightmap[e] = weights[j];
}
// pick random start/goal
mt19937 gen(time(0));
vertex start = random_vertex(g, gen);
vertex goal = random_vertex(g, gen);
cout << "Start vertex: " << name[start] << endl;
cout << "Goal vertex: " << name[goal] << endl;
vector<mygraph_t::vertex_descriptor> p(num_vertices(g));
vector<cost> d(num_vertices(g));
try {
// call astar named parameter interface
astar_search
(g, start,
distance_heuristic<mygraph_t, cost, location*>
(locations, goal),
predecessor_map(&p[0]).distance_map(&d[0]).
visitor(astar_goal_visitor<vertex>(goal)));
} catch(found_goal fg) { // found a path to the goal
list<vertex> shortest_path;
for(vertex v = goal;; v = p[v]) {
shortest_path.push_front(v);
if(p[v] == v)
break;
}
cout << "Shortest path from " << name[start] << " to "
<< name[goal] << ": ";
list<vertex>::iterator spi = shortest_path.begin();
cout << name[start];
for(++spi; spi != shortest_path.end(); ++spi)
cout << " -> " << name[*spi];
cout << endl << "Total travel time: " << d[goal] << endl;
return 0;
}
cout << "Didn't find a path from " << name[start] << "to"
<< name[goal] << "!" << endl;
return 0;
}

View File

@ -0,0 +1,394 @@
#include <boost/graph/floyd_warshall_shortest.hpp>
#include <map>
#include <algorithm>
#include <iostream>
#include <boost/random/linear_congruential.hpp>
#include <boost/graph/graph_utility.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/bellman_ford_shortest_paths.hpp>
#include <boost/graph/random.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/adjacency_matrix.hpp>
#include <boost/test/minimal.hpp>
template <typename T>
struct inf_plus{
T operator()(const T& a, const T& b) const {
T inf = std::numeric_limits<T>::max();
if (a == inf || b == inf){
return inf;
}
return a + b;
}
};
template<typename Graph>
bool acceptance_test(Graph& g, int vec, int e)
{
boost::minstd_rand ran(vec);
{
typename boost::property_map<Graph, boost::vertex_name_t>::type index =
boost::get(boost::vertex_name, g);
typename boost::graph_traits<Graph>::vertex_iterator firstv, lastv,
firstv2, lastv2;
int x = 0;
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
boost::put(index, *firstv, x);
x++;
}
for(int i = 0; i < e; i++){
boost::add_edge(index[ran() % vec], index[ran() % vec], g);
}
typename boost::graph_traits<Graph>::edge_iterator first, last;
typename boost::property_map<Graph, boost::edge_weight_t>::type
local_edge_map = boost::get(boost::edge_weight, g);
for(boost::tie(first, last) = boost::edges(g); first != last; first++){
if (ran() % vec != 0){
boost::put(local_edge_map, *first, ran() % 100);
} else {
boost::put(local_edge_map, *first, 0 - (ran() % 100));
}
}
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_des;
std::map<vertex_des,int> matrixRow;
std::map<vertex_des, std::map<vertex_des ,int> > matrix;
typedef typename boost::property_map<Graph, boost::vertex_distance_t>::type
distance_type;
distance_type distance_row = boost::get(boost::vertex_distance, g);
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
boost::put(distance_row, *firstv, std::numeric_limits<int>::max());
matrixRow[*firstv] = std::numeric_limits<int>::max();
}
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
matrix[*firstv] = matrixRow;
}
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
matrix[*firstv][*firstv] = 0;
}
std::map<vertex_des, std::map<vertex_des, int> > matrix3(matrix);
std::map<vertex_des, std::map<vertex_des, int> > matrix4(matrix);
for(boost::tie(first, last) = boost::edges(g); first != last; first++){
if (matrix[boost::source(*first, g)][boost::target(*first, g)]
!= std::numeric_limits<int>::max()){
matrix[boost::source(*first, g)][boost::target(*first, g)] =
std::min(boost::get(local_edge_map, *first),
matrix[boost::source(*first, g)][boost::target(*first, g)]);
} else {
matrix[boost::source(*first, g)][boost::target(*first, g)] =
boost::get(local_edge_map, *first);
}
}
bool is_undirected =
boost::is_same<typename boost::graph_traits<Graph>::directed_category,
boost::undirected_tag>::value;
if (is_undirected){
for(boost::tie(first, last) = boost::edges(g); first != last; first++){
if (matrix[boost::target(*first, g)][boost::source(*first, g)]
!= std::numeric_limits<int>::max()){
matrix[boost::target(*first, g)][boost::source(*first, g)] =
std::min(boost::get(local_edge_map, *first),
matrix[boost::target(*first, g)][boost::source(*first, g)]);
} else {
matrix[boost::target(*first, g)][boost::source(*first, g)] =
boost::get(local_edge_map, *first);
}
}
}
bool bellman, floyd1, floyd2, floyd3;
std::less<int> compare;
inf_plus<int> combine;
floyd1 =
boost::floyd_warshall_initialized_all_pairs_shortest_paths
(g,
matrix, weight_map(boost::get(boost::edge_weight, g)).
distance_compare(compare). distance_combine(combine).
distance_inf(std::numeric_limits<int>::max()). distance_zero(0));
floyd2 =
boost::floyd_warshall_all_pairs_shortest_paths
(g, matrix3,
weight_map(local_edge_map). distance_compare(compare).
distance_combine(combine).
distance_inf(std::numeric_limits<int>::max()). distance_zero(0));
floyd3 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix4);
boost::dummy_property_map dummy_map;
std::map<vertex_des, std::map<vertex_des, int> > matrix2;
for(boost::tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++){
boost::put(distance_row, *firstv, 0);
bellman =
boost::bellman_ford_shortest_paths
(g, vec,
weight_map(boost::get(boost::edge_weight, g)).
distance_map(boost::get(boost::vertex_distance, g)).
predecessor_map(dummy_map).distance_compare(compare).
distance_combine(combine));
distance_row = boost::get(boost::vertex_distance, g);
for(boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2;
firstv2++){
matrix2[*firstv][*firstv2] = boost::get(distance_row, *firstv2);
boost::put(distance_row, *firstv2, std::numeric_limits<int>::max());
}
if(bellman == false){
break;
}
}
if (bellman != floyd1 || bellman != floyd2 || bellman != floyd3){
std::cout <<
"A negative cycle was detected in one algorithm but not the others. "
<< std::endl;
return false;
}
else if (bellman == false && floyd1 == false && floyd2 == false &&
floyd3 == false){
return true;
}
else {
typename boost::graph_traits<Graph>::vertex_iterator first1, first2,
last1, last2;
for (boost::tie(first1, last1) = boost::vertices(g); first1 != last1;
first1++){
for (boost::tie(first2, last2) = boost::vertices(g); first2 != last2;
first2++){
if (matrix2[*first1][*first2] != matrix[*first1][*first2]){
std::cout << "Algorithms do not match at matrix point "
<< index[*first1] << " " << index[*first2]
<< " Bellman results: " << matrix2[*first1][*first2]
<< " floyd 1 results " << matrix[*first1][*first2]
<< std::endl;
return false;
}
if (matrix2[*first1][*first2] != matrix3[*first1][*first2]){
std::cout << "Algorithms do not match at matrix point "
<< index[*first1] << " " << index[*first2]
<< " Bellman results: " << matrix2[*first1][*first2]
<< " floyd 2 results " << matrix3[*first1][*first2]
<< std::endl;
return false;
}
if (matrix2[*first1][*first2] != matrix4[*first1][*first2]){
std::cout << "Algorithms do not match at matrix point "
<< index[*first1] << " " << index[*first2]
<< " Bellman results: " << matrix2[*first1][*first2]
<< " floyd 3 results " << matrix4[*first1][*first2]
<< std::endl;
return false;
}
}
}
}
}
return true;
}
template<typename Graph>
bool acceptance_test2(Graph& g, int vec, int e)
{
boost::minstd_rand ran(vec);
{
typename boost::property_map<Graph, boost::vertex_name_t>::type index =
boost::get(boost::vertex_name, g);
typename boost::graph_traits<Graph>::vertex_iterator firstv, lastv,
firstv2, lastv2;
int x = 0;
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
boost::put(index, *firstv, x);
x++;
}
boost::generate_random_graph(g, vec, e, ran, true);
typename boost::graph_traits<Graph>::edge_iterator first, last;
typename boost::property_map<Graph, boost::edge_weight_t>::type
local_edge_map = boost::get(boost::edge_weight, g);
for(boost::tie(first, last) = boost::edges(g); first != last; first++){
if (ran() % vec != 0){
boost::put(local_edge_map, *first, ran() % 100);
} else {
boost::put(local_edge_map, *first, 0 - (ran() % 100));
}
}
typedef typename boost::graph_traits<Graph>::vertex_descriptor vertex_des;
std::map<vertex_des,int> matrixRow;
std::map<vertex_des, std::map<vertex_des ,int> > matrix;
typedef typename boost::property_map<Graph, boost::vertex_distance_t>::type
distance_type;
distance_type distance_row = boost::get(boost::vertex_distance, g);
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
boost::put(distance_row, *firstv, std::numeric_limits<int>::max());
matrixRow[*firstv] = std::numeric_limits<int>::max();
}
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
matrix[*firstv] = matrixRow;
}
for(boost::tie(firstv, lastv) = boost::vertices(g); firstv != lastv;
firstv++){
matrix[*firstv][*firstv] = 0;
}
std::map<vertex_des, std::map<vertex_des, int> > matrix3(matrix);
std::map<vertex_des, std::map<vertex_des, int> > matrix4(matrix);
for(boost::tie(first, last) = boost::edges(g); first != last; first++){
if (matrix[boost::source(*first, g)][boost::target(*first, g)]
!= std::numeric_limits<int>::max()){
matrix[boost::source(*first, g)][boost::target(*first, g)] =
std::min(boost::get(local_edge_map, *first),
matrix[boost::source(*first, g)][boost::target(*first, g)]);
} else {
matrix[boost::source(*first, g)][boost::target(*first, g)] =
boost::get(local_edge_map, *first);
}
}
bool is_undirected =
boost::is_same<typename boost::graph_traits<Graph>::directed_category,
boost::undirected_tag>::value;
if (is_undirected){
for(boost::tie(first, last) = boost::edges(g); first != last; first++){
if (matrix[boost::target(*first, g)][boost::source(*first, g)]
!= std::numeric_limits<int>::max()){
matrix[boost::target(*first, g)][boost::source(*first, g)] =
std::min(boost::get(local_edge_map, *first),
matrix[boost::target(*first, g)][boost::source(*first, g)]);
} else {
matrix[boost::target(*first, g)][boost::source(*first, g)] =
boost::get(local_edge_map, *first);
}
}
}
bool bellman, floyd1, floyd2, floyd3;
std::less<int> compare;
inf_plus<int> combine;
floyd1 =
boost::floyd_warshall_initialized_all_pairs_shortest_paths
(g,
matrix, weight_map(boost::get(boost::edge_weight, g)).
distance_compare(compare). distance_combine(combine).
distance_inf(std::numeric_limits<int>::max()). distance_zero(0));
floyd2 =
boost::floyd_warshall_all_pairs_shortest_paths
(g, matrix3,
weight_map(local_edge_map). distance_compare(compare).
distance_combine(combine).
distance_inf(std::numeric_limits<int>::max()). distance_zero(0));
floyd3 = boost::floyd_warshall_all_pairs_shortest_paths(g, matrix4);
boost::dummy_property_map dummy_map;
std::map<vertex_des, std::map<vertex_des, int> > matrix2;
for(boost::tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++){
boost::put(distance_row, *firstv, 0);
bellman =
boost::bellman_ford_shortest_paths
(g, vec,
weight_map(boost::get(boost::edge_weight, g)).
distance_map(boost::get(boost::vertex_distance, g)).
predecessor_map(dummy_map).distance_compare(compare).
distance_combine(combine));
distance_row = boost::get(boost::vertex_distance, g);
for(boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2;
firstv2++){
matrix2[*firstv][*firstv2] = boost::get(distance_row, *firstv2);
boost::put(distance_row, *firstv2, std::numeric_limits<int>::max());
}
if(bellman == false){
break;
}
}
if (bellman != floyd1 || bellman != floyd2 || bellman != floyd3){
std::cout <<
"A negative cycle was detected in one algorithm but not the others. "
<< std::endl;
return false;
}
else if (bellman == false && floyd1 == false && floyd2 == false &&
floyd3 == false){
return true;
}
else {
typename boost::graph_traits<Graph>::vertex_iterator first1, first2,
last1, last2;
for (boost::tie(first1, last1) = boost::vertices(g); first1 != last1;
first1++){
for (boost::tie(first2, last2) = boost::vertices(g); first2 != last2;
first2++){
if (matrix2[*first1][*first2] != matrix[*first1][*first2]){
std::cout << "Algorithms do not match at matrix point "
<< index[*first1] << " " << index[*first2]
<< " Bellman results: " << matrix2[*first1][*first2]
<< " floyd 1 results " << matrix[*first1][*first2]
<< std::endl;
return false;
}
if (matrix2[*first1][*first2] != matrix3[*first1][*first2]){
std::cout << "Algorithms do not match at matrix point "
<< index[*first1] << " " << index[*first2]
<< " Bellman results: " << matrix2[*first1][*first2]
<< " floyd 2 results " << matrix3[*first1][*first2]
<< std::endl;
return false;
}
if (matrix2[*first1][*first2] != matrix4[*first1][*first2]){
std::cout << "Algorithms do not match at matrix point "
<< index[*first1] << " " << index[*first2]
<< " Bellman results: " << matrix2[*first1][*first2]
<< " floyd 3 results " << matrix4[*first1][*first2]
<< std::endl;
return false;
}
}
}
}
}
return true;
}
int test_main(int, char*[])
{
typedef boost::adjacency_list<boost::listS, boost::listS, boost::directedS,
boost::property<boost::vertex_distance_t, int,
boost::property<boost::vertex_name_t, int> > ,
boost::property<boost::edge_weight_t, int> > Digraph;
Digraph adjlist_digraph;
BOOST_TEST(acceptance_test2(adjlist_digraph, 100, 2000));
typedef boost::adjacency_matrix<boost::undirectedS,
boost::property<boost::vertex_distance_t, int,
boost::property<boost::vertex_name_t, int> > ,
boost::property<boost::edge_weight_t, int> > Graph;
Graph matrix_graph(100);
BOOST_TEST(acceptance_test(matrix_graph, 100, 2000));
return 0;
}

View File

@ -6,9 +6,12 @@
// Authors: Douglas Gregor
// Andrew Lumsdaine
#include <boost/graph/fruchterman_reingold.hpp>
#include <boost/graph/random_layout.hpp>
#include <boost/graph/kamada_kawai_spring_layout.hpp>
#include <boost/graph/circle_layout.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/test/minimal.hpp>
#include <iostream>
#include <boost/limits.hpp>
@ -149,7 +152,7 @@ test_triangle(Graph*)
side_length(50.0));
BOOST_TEST(ok);
std::cout << "Triangle layout.\n";
std::cout << "Triangle layout (Kamada-Kawai).\n";
print_graph_layout(g, get(vertex_position, g));
}
@ -191,10 +194,32 @@ test_cube(Graph*)
kamada_kawai_done());
BOOST_TEST(ok);
std::cout << "Cube layout.\n";
std::cout << "Cube layout (Kamada-Kawai).\n";
print_graph_layout(g, get(vertex_position, g));
dump_graph_layout("cube", g, get(vertex_position, g));
minstd_rand gen;
random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0,
gen);
std::vector<point> displacements(num_vertices(g));
fruchterman_reingold_force_directed_layout
(g,
get(vertex_position, g),
50.0,
50.0,
square_distance_attractive_force(),
square_distance_repulsive_force(),
all_force_pairs(),
linear_cooling<double>(100),
make_iterator_property_map(displacements.begin(),
get(vertex_index, g)));
std::cout << "Cube layout (Fruchterman-Reingold).\n";
print_graph_layout(g, get(vertex_position, g));
dump_graph_layout("cube-fr", g, get(vertex_position, g));
}
template<typename Graph>
@ -235,10 +260,88 @@ test_triangular(Graph*)
kamada_kawai_done());
BOOST_TEST(ok);
std::cout << "Triangular layout.\n";
std::cout << "Triangular layout (Kamada-Kawai).\n";
print_graph_layout(g, get(vertex_position, g));
dump_graph_layout("triangular", g, get(vertex_position, g));
dump_graph_layout("triangular-kk", g, get(vertex_position, g));
minstd_rand gen;
random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0,
gen);
dump_graph_layout("random", g, get(vertex_position, g));
std::vector<point> displacements(num_vertices(g));
fruchterman_reingold_force_directed_layout
(g,
get(vertex_position, g),
50.0,
50.0,
attractive_force(square_distance_attractive_force()).
cooling(linear_cooling<double>(100)));
std::cout << "Triangular layout (Fruchterman-Reingold).\n";
print_graph_layout(g, get(vertex_position, g));
dump_graph_layout("triangular-fr", g, get(vertex_position, g));
}
template<typename Graph>
void
test_disconnected(Graph*)
{
enum {A, B, C, D, E, F, G, H};
simple_edge triangular_edges[13] = {
{A, B}, {B, C}, {C, A},
{D, E}, {E, F}, {F, G}, {G, H}, {H, D},
{D, F}, {F, H}, {H, E}, {E, G}, {G, D}
};
Graph g(&triangular_edges[0], &triangular_edges[13], 8);
typedef typename graph_traits<Graph>::edge_iterator edge_iterator;
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
vertex_iterator vi, vi_end;
int i = 0;
for (tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi)
put(vertex_index, g, *vi, i++);
edge_iterator ei, ei_end;
for (tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) {
put(edge_weight, g, *ei, 1.0);
std::cerr << "(" << (char)(get(vertex_index, g, source(*ei, g)) + 'A')
<< ", " << (char)(get(vertex_index, g, target(*ei, g)) + 'A')
<< ") ";
}
std::cerr << std::endl;
circle_graph_layout(g, get(vertex_position, g), 25.0);
bool ok = kamada_kawai_spring_layout(g,
get(vertex_position, g),
get(edge_weight, g),
side_length(50.0),
kamada_kawai_done());
BOOST_TEST(!ok);
minstd_rand gen;
random_graph_layout(g, get(vertex_position, g), -25.0, 25.0, -25.0, 25.0,
gen);
std::vector<point> displacements(num_vertices(g));
fruchterman_reingold_force_directed_layout
(g,
get(vertex_position, g),
50.0,
50.0,
attractive_force(square_distance_attractive_force()).
cooling(linear_cooling<double>(50)));
std::cout << "Disconnected layout (Fruchterman-Reingold).\n";
print_graph_layout(g, get(vertex_position, g));
dump_graph_layout("disconnected-fr", g, get(vertex_position, g));
}
int test_main(int, char*[])
@ -253,6 +356,6 @@ int test_main(int, char*[])
test_circle_layout((Graph*)0, 5);
test_cube((Graph*)0);
test_triangular((Graph*)0);
test_disconnected((Graph*)0);
return 0;
}