2
0
mirror of https://github.com/boostorg/graph.git synced 2026-01-19 04:12:11 +00:00

Merged Boost.Graph changes from trunk for 1.53

[SVN r82061]
This commit is contained in:
Jeremiah Willcock
2012-12-17 23:59:46 +00:00
parent 3419d42acc
commit 22b521ecf4
41 changed files with 2795 additions and 150 deletions

View File

@@ -37,10 +37,28 @@ template <typename VertexListGraph,
typename P, typename T, typename R>
void
astar_search_no_init
(const IncidenceGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
<a href="AStarHeuristic.html">AStarHeuristic</a> h, const bgl_named_params&lt;P, T, R&gt;&amp; params);
template &lt;typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R&gt;
void
astar_search_tree
(const 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);
template &lt;typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R&gt;
void
astar_search_no_init_tree
(const IncidenceGraph &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,
@@ -60,7 +78,23 @@ astar_search
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero);
<i>// Version that does not initialize property maps (used for implicit graphs)</i>
template &lt;typename VertexListGraph, typename AStarHeuristic,
typename <a href="AStarVisitor.html">AStarVisitor</a>, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap,
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_tree
(const VertexListGraph &amp;g,
typename graph_traits&lt;VertexListGraph&gt;::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero);
<i>// Versions that do not initialize property maps (used for implicit graphs)</i>
template &lt;typename IncidenceGraph, typename AStarHeuristic,
typename <a href="AStarVisitor.html">AStarVisitor</a>, typename PredecessorMap,
typename CostMap, typename DistanceMap,
@@ -82,6 +116,22 @@ astar_search_no_init
<b>Note that the index_map and color parameters are swapped in
astar_search_no_init() relative to astar_search(); the named parameter
interfaces are not affected.</b>
template &lt;typename IncidenceGraph, typename AStarHeuristic,
typename <a href="AStarVisitor.html">AStarVisitor</a>, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap,
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_no_init_tree
(const IncidenceGraph &amp;g,
typename graph_traits&lt;IncidenceGraph&gt;::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero);
</PRE>
<P>
@@ -125,7 +175,8 @@ useful for searching large state spaces -- in game-playing scenarios
the entire graph. Implicit searches can be performed with this
implementation of A* by creating special visitors that generate
neighbors of newly-expanded vertices. Please note that
<tt>astar_search_no_init()</tt> must be used for implicit graphs; the basic
<tt>astar_search_no_init()</tt> or <tt>astar_search_no_init_tree()</tt> must be
used for implicit graphs; the basic
<tt>astar_search()</tt> function requires a graph that models
the <a href="VertexListGraph.html">Vertex List Graph</a> concept. Both
versions
@@ -134,8 +185,9 @@ href="IncidenceGraph.html">Incidence Graph</a> concept.
</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''
For the non-tree versions of the algorithm,
this implementation of A* is based on an OPEN/CLOSED list formulation.
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
@@ -146,7 +198,11 @@ 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.
are colored white. For the versions of the algorithm whose names end in
<tt>_tree</tt>, all vertices are assumed to always be white, leading to
checking for repeated vertices being done using the distance map. If a dummy
value is used for the distance map and the graph contains cycles, the algorithm
will probably enter an infinite loop.
</P>
<P>
@@ -292,7 +348,8 @@ IN: <tt>weight_map(WeightMap w_map)</tt>
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
num_vertices(g))</tt>. This is necessary in non-tree versions of the
algorithm 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/doc/ReadablePropertyMap.html"><tt>Readable
@@ -338,7 +395,10 @@ UTIL/OUT: <tt>distance_map(DistanceMap d_map)</tt>
<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>
provided by the <tt>compare</tt> function object. A
<tt>constant_writable_property_map</tt> returning the infinity value can be
used for this parameter in tree versions of the algorithm when the graph does
not contain a directed cycle.<br>
<b>Default:</b> <tt>shared_array_property_map</tt>
with the same value type as the
@@ -355,7 +415,10 @@ UTIL/OUT: <tt>rank_map(CostMap c_map)</tt>
<tt>h</tt>) from the vertex to a goal. The type <tt>CostMap</tt>
must be a model of <a
href="../../property_map/doc/ReadWritePropertyMap.html"><tt>Read/Write
Property Map</tt></a>. The vertex descriptor type of the graph
Property Map</tt></a> in non-tree versions of the algorithm, and <a
href="../../property_map/doc/WritablePropertyMap.html"><tt>Writable Property
Map</tt></a> in tree versions of the algorithm. 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
@@ -364,7 +427,8 @@ UTIL/OUT: <tt>rank_map(CostMap c_map)</tt>
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>
map. In tree versions of the algorithm, <tt>null_property_map</tt> can be
used for this parameter.<br>
<b>Default:</b> <tt>shared_array_property_map</tt>
with the same value type as the
@@ -375,7 +439,8 @@ UTIL/OUT: <tt>rank_map(CostMap c_map)</tt>
UTIL/OUT: <tt>color_map(ColorMap c_map)</tt>
<blockquote>
This is used during the execution of the algorithm to mark the
This is used during the execution of non-tree versions 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

View File

@@ -396,7 +396,7 @@ disregard the directionality in the function names. The example below
demonstrates using the <TT>out_edges()</TT>, <TT>source()</TT>, and
<TT>target()</TT> with an undirected graph. The source code for this
example and the following one can be found in <a
href="../example/undirected.cpp"><TT>examples/undirected.cpp</TT></a>.
href="../example/undirected_adjacency_list.cpp"><TT>example/undirected_adjacency_list.cpp</TT></a>.
<P>
<PRE>

View File

@@ -158,7 +158,7 @@ href="../example/max_flow.cpp"><tt>example/max_flow.cpp</tt></a>.
#include &lt;boost/config.hpp&gt;
#include &lt;iostream&gt;
#include &lt;string&gt;
#include &lt;boost/graph/push_relabel_map_flow.hpp&gt;
#include &lt;boost/graph/push_relabel_max_flow.hpp&gt;
#include &lt;boost/graph/adjacency_list.hpp&gt;
#include &lt;boost/graph/read_dimacs.hpp&gt;

View File

@@ -20,7 +20,7 @@ http://www.boost.org/LICENSE_1_0.txt)
Authors: Tiago de Paula Peixoto -->
<pre class="literal-block">
void read_graphml(std::istream&amp; in, MutableGraph&amp; graph,
dynamic_properties&amp; dp);
dynamic_properties&amp; dp, size_t graph_index = 0);
</pre>
<p>The <tt class="docutils literal"><span class="pre">read_graphml</span></tt> function interprets a graph described using the
<a class="reference external" href="http://graphml.graphdrawing.org/">GraphML</a> format and builds a BGL graph that captures that
@@ -39,6 +39,10 @@ this object, using the GraphML attribute names as the property names,
and with the appropriate C++ value type based on the GraphML attribute type
definition. Graph properties are also set with the same
<a class="reference external" href="../../property_map/doc/dynamic_property_map.html">dynamic_properties</a> object, where the key type is the type of the graph itself.</p>
<p>If the file contains multiple graphs, the <tt class="docutils literal"><span class="pre">graph_index</span></tt> parameter controls
which graph will be loaded. It defaults to <tt class="docutils literal"><span class="pre">0</span></tt>, meaning that the first graph
in the file will be loaded. If <tt class="docutils literal"><span class="pre">graph_index</span></tt> is greater than or equal to the
number of graphs in the file, an empty graph will be returned.</p>
<dl class="docutils">
<dt>Requirements:</dt>
<dd><ul class="first last simple">
@@ -156,7 +160,7 @@ graph.</li>
</div>
<div class="footer">
<hr class="footer" />
Generated on: 2009-06-12 00:41 UTC.
Generated on: 2012-11-12 22:25 UTC.
Generated by <a class="reference external" href="http://docutils.sourceforge.net/">Docutils</a> from <a class="reference external" href="http://docutils.sourceforge.net/rst.html">reStructuredText</a> source.
</div>

View File

@@ -19,7 +19,7 @@ __ ../../../index.htm
::
void read_graphml(std::istream& in, MutableGraph& graph,
dynamic_properties& dp);
dynamic_properties& dp, size_t graph_index = 0);
The ``read_graphml`` function interprets a graph described using the
@@ -42,6 +42,11 @@ and with the appropriate C++ value type based on the GraphML attribute type
definition. Graph properties are also set with the same
dynamic_properties_ object, where the key type is the type of the graph itself.
If the file contains multiple graphs, the ``graph_index`` parameter controls
which graph will be loaded. It defaults to ``0``, meaning that the first graph
in the file will be loaded. If ``graph_index`` is greater than or equal to the
number of graphs in the file, an empty graph will be returned.
Requirements:
- The type of the graph must model the `Mutable Graph`_ concept.
- The type of the iterator must model the `Multi-Pass Iterator`_

View File

@@ -45,7 +45,7 @@ public:
small_world_iterator();
small_world_iterator(RandomGenerator&amp; gen, vertices_size_type n,
vertices_size_type k, double probability,
vertices_size_type k, double probability = 0.,
bool allow_self_loops = false);
// Iterator operations
reference operator*() const;
@@ -82,7 +82,7 @@ Constructs a past-the-end iterator.
<pre>
small_world_iterator(RandomGenerator&amp; gen, vertices_size_type n,
vertices_size_type k, double probability,
vertices_size_type k, double probability = 0.,
bool allow_self_loops = false);
</pre>
<blockquote>

View File

@@ -172,7 +172,7 @@
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>
<li><a href="r_c_shortest_paths.html"><tt>r_c_shortest_paths</tt> - resource-constrained shortest paths</a></li>
<li><a href="astar_search.html"><tt>astar_search</tt></a></li>
<li><a href="astar_search.html"><tt>astar_search</tt> (A* search algorithm)</a></li>
</OL>
<LI>Minimum Spanning Tree Algorithms
<OL>
@@ -240,6 +240,7 @@
<li>Graph Structure Comparisons
<ol>
<LI><A href="isomorphism.html"><tt>isomorphism</tt></A>
<LI><A href="vf2_sub_graph_iso.html"><tt>vf2_sub_graph_iso</tt> (VF2 subgraph isomorphism algorithm)</A>
<li><a href="mcgregor_common_subgraphs.html"><tt>mcgregor_common_subgraphs</tt></a></li>
</ol>

517
doc/vf2_sub_graph_iso.html Executable file
View File

@@ -0,0 +1,517 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<!--
Copyright (C) Flavio De Lorenzi 2012
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)
-->
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=iso-8859-15">
<title>Boost Graph Library: VF2 (Sub)Graph Isomorphism</title>
<style type="text/css">
<!--
body {
color: black;
background-color: white;
}
.comment {
color: #333333;
}
a {
color: blue;
}
a:visited {
color: #551A8B;
}
-->
</style>
</head>
<body>
<p><img src="../../../boost.png" alt="C++ Boost" width="277" height="86"></p>
<h1>
<tt>vf2_subgraph_iso</tt>
</h1>
<pre>
<em class="comment">// All defaults interface</em>
template &lt;typename GraphSmall,
typename GraphLarge,
typename SubGraphIsoMapCallback&gt;
bool vf2_subgraph_iso(const GraphSmall&amp; graph_small,
const GraphLarge&amp; graph_large,
SubGraphIsoMapCallback user_callback)
<em class="comment">// Named parameter version</em>
template &lt;typename GraphSmall,
typename GraphLarge,
typename VertexOrderSmall,
typename SubGraphIsoMapCallback,
typename Param,
typename Tag,
typename Rest&gt;
bool vf2_subgraph_iso(const GraphSmall&amp; graph_small,
const GraphLarge&amp; graph_large,
SubGraphIsoMapCallback user_callback,
const VertexOrderSmall&amp; vertex_order_small,
const bgl_named_params&lt;Param, Tag, Rest&gt;&amp; params)
<em class="comment">// Non-named parameter version</em>
template &lt;typename GraphSmall,
typename GraphLarge,
typename <a href="../../property_map/doc/ReadablePropertyMap.html">IndexMapSmall</a>,
typename <a href="../../property_map/doc/ReadablePropertyMap.html">IndexMapLarge</a>,
typename VertexOrderSmall,
typename <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">EdgeEquivalencePredicate</a>,
typename <a href="http://www.sgi.com/tech/stl/BinaryFunction.html">VertexEquivalencePredicate</a>,
typename SubGraphIsoMapCallback&gt;
bool vf2_subgraph_iso(const GraphSmall&amp; graph_small,
const GraphLarge&amp; graph_large,
SubGraphIsoMapCallback user_callback,
IndexMapSmall index_map_small,
IndexMapLarge index_map_large,
const VertexOrderSmall&amp; vertex_order_small,
EdgeEquivalencePredicate edge_comp,
VertexEquivalencePredicate vertex_comp)
</pre>
<p>
An isomorphism between two graphs <em>G<sub>1</sub>=(V<sub>1</sub>, E<sub>1</sub>)</em>
and <em>G<sub>2</sub>=(V<sub>2</sub>, E<sub>2</sub>)</em> is a
bijective mapping <em>M</em> of the vertices of one graph to vertices of the other
graph that preserves the edge structure of the graphs. <em>M</em> is said to be a
graph-subgraph isomorphism if and only if <em>M</em> is an isomorphism between
<em>G<sub>1</sub></em> and a subgraph of <em>G<sub>2</sub></em>.
</p>
<p>
This function finds all graph-subgraph isomorphism mappings between
graphs <tt>graph_small</tt> and <tt>graph_large</tt> and outputs them to
<tt>user_callback</tt>. It continues until <tt>user_callback</tt>
returns true or the search space has been fully explored. <tt>vf2_subgraph_iso</tt>
returns true if a graph-subgraph isomorphism exists and false otherwise.
<tt>EdgeEquivalencePredicate</tt> and
<tt>VertexEquivalencePredicate</tt> predicates are used to test whether
edges and vertices are equivalent. To use property maps for equivalence,
see
<tt><a href="./mcgregor_common_subgraphs.html#make_property_map_equivalent">
make_property_map_equivalent</a></tt>
function. By default <tt><a href="./mcgregor_common_subgraphs.html#always_equivalent">
always_equivalent</a></tt> is used, which returns
true for any pair of vertices or edges.
</p>
<p>
The current implementation is based on the <em>VF2</em> algorithm,
introduced by Cordella et al. An in-depth description of the algorithm is
given in [<a href="#cordella2001">1</a>] and [<a href="#cordella2004">2</a>]
and references therein. The original code by P. Foggia and collaborators can
be found at [<a href="#foggia_etal">3</a>]. In brief, the process of
finding a mapping between the two graphs <em>G<sub>1</sub></em> and
<em>G<sub>2</sub></em> determines the isomorphism mapping <em>M</em>,
which associates vertices <em>G<sub>1</sub></em> with vertices of
<em>G<sub>2</sub></em> and vice versa. It can be described by means of a
state space representation which is created by the algorithm
while exploring the search graph in depth-first fashion.
Each state <em>s</em> of the matching process
can be associated with a partial mapping <em>M(s)</em>. At each level,
the algorithm computes the set of the vertex pairs that are candidates to
be added to the current state <em>s</em>. If a pair of vertices
(<em>v, w</em>) is feasible, the mapping is extended and the associated
successor state <em>s'</em> is computed.
The whole procedure is then repeated for state <em>s'</em>.
</p>
<h3>Where Defined</h3>
<p>
<a href="../../../boost/graph/vf2_sub_graph_iso.hpp">
<tt>boost/graph/vf2_sub_graph_iso.hpp</tt></a><br>
All functions are defined in the boost namespace.
</p>
<h3>Parameters</h3>
<p>IN: <tt>const GraphSmall&amp; graph_small</tt></p>
<blockquote>
<p>
The (first) smaller graph (fewer vertices) of the pair to be tested for
isomorphism. The type <tt>GraphSmall</tt> must be a
model of
<a href="./VertexListGraph.html">Vertex List Graph</a>,
<a href="./EdgeListGraph.html">Edge List Graph</a>,
<a href="./BidirectionalGraph.html">Bidirectional Graph</a> and
<a href="./AdjacencyMatrix.html">Adjacency Matrix</a>.
The edge descriptors <tt>graph_traits&lt;GraphSmall&gt;::edge_descriptor</tt>
must be <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThan Comparable</a>, cf. also the remark <a href="#notes">below</a>.
</p>
</blockquote>
<p>IN: <tt>const GraphLarge&amp; graph_large</tt></p>
<blockquote>
<p>
The (second) larger graph to be tested.
Type <tt>GraphLarge</tt> must be a model of
<a href="./VertexListGraph.html">Vertex List Graph</a>,
<a href="./EdgeListGraph.html">Edge List Graph</a>,
<a href="./BidirectionalGraph.html">Bidirectional Graph</a> and
<a href="./AdjacencyMatrix.html">Adjacency Matrix</a>.
The edge descriptors <tt>graph_traits&lt;GraphLarge&gt;::edge_descriptor</tt>
must be <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThan Comparable</a>, cf. also the remark <a href="#notes">below</a>.
</p>
</blockquote>
<p>OUT: <tt>SubGraphIsoMapCallback user_callback</tt></p>
<blockquote>
<p>
A function object to be called when a graph-subgraph isomorphism has been discovered. The
<tt>operator()</tt> must have following form:
</p>
<pre>
template &lt;typename CorrespondenceMap1To2,
typename CorrespondenceMap2To1&gt;
bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1 g) const
</pre>
<p>
Both the <tt>CorrespondenceMap1To2</tt>
and <tt>CorresondenceMap2To1</tt> types are models
of <a href="../../property_map/doc/ReadablePropertyMap.html">Readable
Property Map</a> and map equivalent vertices across the two
graphs given to <tt>vf2_subgraph_iso</tt> (or <tt>vf2_graph_iso</tt>). For
instance, if <tt>v</tt> is
from <tt>graph_small</tt>, <tt>w</tt> is from <tt>graph_large</tt>,
and the vertices can be considered equivalent,
then <tt>get(f, v)</tt> will be <tt>w</tt> and <tt>get(g, w)</tt>
will be <tt>v</tt>. If any vertex, say <tt>v</tt> in <tt>graph_small</tt>,
does not match a vertex in <tt>graph_large</tt> ,
then <tt>get(f, v)</tt> will be <tt>graph_traits&lt;GraphLarge&gt;::null_vertex()</tt>.
Likewise for any unmatched vertices from <tt>graph_large</tt>,
<tt>get(g, w)</tt> will be <tt>graph_traits&lt;GraphSmall&gt;::null_vertex()</tt>.
Returning false from the callback will abort the search immediately. Otherwise,
the entire search space will be explored. A "default" print callback
is provided as a <a href="#vf2_callback">utility function</a>.
</p>
</blockquote>
<p>IN: <tt>const VertexOrderSmall&amp; vertex_order_small</tt></p>
<blockquote>
<p>
The ordered vertices of the smaller (first) graph <tt>graph_small</tt>.
During the matching process the vertices are examined in the order given by
<tt>vertex_order_small</tt>. Type <tt>VertexOrderSmall</tt> must be a model
of <a href="http://www.sgi.com/tech/stl/Container.html">ContainerConcept</a>
with value type
<tt>graph_traits&lt;GraphSmall&gt;::vertex_descriptor</tt>.
<br>
<b>Default</b> The vertices are ordered by multiplicity of
in/out degrees.
</p>
</blockquote>
<h3>Named Parameters</h3>
<p>IN: <tt>vertex_index1(IndexMapSmall index_map_small)</tt></p>
<blockquote>
<p>
This maps each vertex to an integer in the range <tt>[0, num_vertices(graph_small))</tt>.
Type <tt>IndexMapSmall</tt> must be a model of
<a href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map</a>.
<br>
<b>Default:</b> <tt>get(vertex_index, graph_small)</tt>
</p>
</blockquote>
<p>IN: <tt>vertex_index2(IndexMapLarge index_map_large)</tt></p>
<blockquote>
<p>
This maps each vertex to an integer in the range <tt>[0, num_vertices(graph_large))</tt>.
Type <tt>IndexMapLarge</tt> must be a model of
<a href="../../property_map/doc/ReadablePropertyMap.html">Readable Property Map</a>.
<br>
<b>Default:</b> <tt>get(vertex_index, graph_large)</tt>
</p>
</blockquote>
<p>IN: <tt>edges_equivalent(EdgeEquivalencePredicate edge_comp)</tt></p>
<blockquote>
<p>
This function object is used to determine if edges between the two graphs
<tt>graph_small</tt> and <tt>graph_large</tt> are equivalent.
Type <tt>EdgeEquivalencePredicate</tt> must be a model of
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary
Predicate</a> and have argument types of
<tt>graph_traits&lt;GraphSmall&gt;::edge_descriptor</tt> and
<tt>graph_traits&lt;GraphLarge&gt;::edge_descriptor</tt>.
The edge descriptors must be <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThan Comparable</a>. A return value of true indicates that the edges are equivalent.
<br>
<b>Default:</b> <tt><a href="./mcgregor_common_subgraphs.html#always_equivalent">
always_equivalent</a></tt>
</p>
</blockquote>
<p>IN: <tt>vertices_equivalent(VertexEquivalencePredicate vertex_comp)</tt></p>
<blockquote>
<p>
This function object is used to determine if vertices between the two graphs
<tt>graph_small</tt> and <tt>graph_large</tt> are equivalent.
Type <tt>VertexEquivalencePredicate</tt> must be a model of
<a href="http://www.sgi.com/tech/stl/BinaryPredicate.html">Binary Predicate</a>
and have argument types of
<tt>graph_traits&lt;GraphSmall&gt;::vertex_descriptor</tt> and
<tt>graph_traits&lt;GraphLarge&gt;::vertex_descriptor</tt>. A return value of true
indicates that the vertices are equivalent.
<br>
<b>Default:</b> <tt><a href="./mcgregor_common_subgraphs.html#always_equivalent">
always_equivalent</a></tt>
</p>
</blockquote>
<h3>Related Functions</h3>
<p>
Non-named parameter, named-parameter and all default parameter versions of
function
</p>
<p><tt>vf2_graph_iso(...)</tt></p>
<p>
for isomorphism testing take the same parameters as the corresponding
functions <tt>vf2_subgraph_iso</tt> for subgraph isomorphism testing.
The algorithm finds all isomorphism mappings between graphs
<tt>graph1</tt> and <tt>graph2</tt> and outputs them to
<tt>user_callback</tt>. It continues until <tt>user_callback</tt>
returns true or the search space has been fully explored. As before,
<tt>EdgeEquivalencePredicate</tt> and
<tt>VertexEquivalencePredicate</tt> predicates are used to test
whether edges and vertices are equivalent. By default
<tt>always_equivalent</tt> is used.
</p>
<h3>Utility Functions and Structs</h3>
<p>
<tt id="vf2_callback">
template&lt;typename Graph1,
typename Graph2&gt;
struct vf2_print_callback
</tt>
</p>
<blockquote>
<p>
Callback function object that prints out the correspondences between vertices
of <tt>Graph1</tt> and <tt>Graph2</tt>. The constructor takes
the two graphs <em>G<sub>1</sub></em> and <em>G<sub>2</sub></em>.
</p>
</blockquote>
<pre>
template&lt;typename Graph&gt;
std::vector&lt;typename graph_traits&lt;Graph&gt;::vertex_descriptor&gt;
vertex_order_by_mult(const Graph&amp; graph)
</pre>
<blockquote>
<p>
Returns a vector containing the vertices of a graph, sorted
by multiplicity of in/out degrees.
</p>
</blockquote>
<pre>
<em class="comment">// Variant of verify_subgraph_iso with all default parameters</em>
template&lt;typename Graph1,
typename Graph2,
typename CorresponenceMap1To2&gt;
inline bool verify_vf2_subgraph_iso(const Graph1&amp; graph1, const Graph2&amp; graph2,
const CorresponenceMap1To2 f)
<em class="comment">// Verifies a graph (sub)graph isomorphism map</em>
template&lt;typename Graph1,
typename Graph2,
typename CorresponenceMap1To2,
typename EdgeEquivalencePredicate,
typename VertexEquivalencePredicate&gt;
inline bool verify_vf2_subgraph_iso(const Graph1&amp; graph1, const Graph2&amp; graph2,
const CorresponenceMap1To2 f,
EdgeEquivalencePredicate edge_comp,
VertexEquivalencePredicate vertex_comp)
</pre>
<blockquote>
<p>
This function can be used to verify a (sub)graph isomorphism
mapping <em>f</em>. The parameters are analogous to
function <tt>vf2_subgraph_iso</tt> (<tt>vf2_graph_iso</tt>).
</p>
</blockquote>
<h3>Complexity</h3>
<p>
Spatial and time complexity are given in [<a href="#cordella2004">2</a>]. The spatial
complexity of VF2 is of order <em>O(V)</em>, where V is the (maximum) number
of vertices of the two graphs. Time complexity is <em>O(V<sup>2</sup>)</em> in the best case and
<em>O(V!&middot;V)</em> in the worst case.
</p>
<h3>Examples</h3>
<h4>Example 1</h4>
<p>
In the example below, a small graph <tt>graph1</tt> and a larger graph
<tt>graph2</tt> are defined. Here small and large refers to the number of
vertices of the graphs. <tt>vf2_subgraph_iso</tt> computes all the
subgraph isomorphism mappings between the two graphs and outputs them
via <tt>callback</tt>.
</p>
<pre>
typedef adjacency_list&lt;setS, vecS, bidirectionalS&gt; graph_type;
<em class="comment">// Build graph1</em>
int num_vertices1 = 8; graph_type graph1(num_vertices1);
add_edge(0, 6, graph1); add_edge(0, 7, graph1);
add_edge(1, 5, graph1); add_edge(1, 7, graph1);
add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1);
add_edge(3, 4, graph1);
<em class="comment">// Build graph2</em>
int num_vertices2 = 9; graph_type graph2(num_vertices2);
add_edge(0, 6, graph2); add_edge(0, 8, graph2);
add_edge(1, 5, graph2); add_edge(1, 7, graph2);
add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2);
add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2);
<em class="comment">
// Create callback to print mappings</em>
vf2_print_callback&lt;graph_type, graph_type&gt; callback(graph1, graph2);
<em class="comment">
// Print out all subgraph isomorphism mappings between graph1 and graph2.
// Vertices and edges are assumed to be always equivalent.</em>
vf2_subgraph_iso(graph1, graph2, callback);
</pre>
<p>
The complete example can be found under
<a href="../example/vf2_sub_graph_iso_example.cpp"><tt>examples/vf2_sub_graph_iso_example.cpp</tt></a>.
<br>
</p>
<h4>Example 2</h4>
<p>
In this example, the subgraph isomorphism mappings between multi-graphs are computed. The vertices
and edges of the multi-graphs are distinguished using property maps.
</p>
<pre>
<em class="comment">// Define edge and vertex properties</em>
typedef property&lt;edge_name_t, char&gt; edge_property;
typedef property&lt;vertex_name_t, char, property&lt;vertex_index_t, int&gt; &gt; vertex_property;
<em class="comment">// Using a vecS graphs => the index maps are implicit.</em>
typedef adjacency_list&lt;vecS, vecS, bidirectionalS, vertex_property, edge_property&gt; graph_type;
<em class="comment">// Create graph1</em>
graph_type graph1;
<em class="comment">// Add vertices... </em>
add_vertex(vertex_property('a'), graph1);
...
<em class="comment">//... and edges </em>
add_edge(0, 1, edge_property('b'), graph1);
add_edge(0, 1, edge_property('b'), graph1);
...
<em class="comment">// Create graph2 </em>
graph_type graph2;
add_vertex(vertex_property('a'), graph2);
...
add_edge(0, 1, edge_property('a'), graph2);
...
</pre>
<p>
To distinguish vertices and edges with property maps, binary predicates are created using the
<tt><a href="./mcgregor_common_subgraphs.html#make_property_map_equivalent">
make_property_map_equivalent</a></tt> function:
</p>
<pre>
<em class="comment">// Create the vertex binary predicate</em>
typedef property_map&lt;graph_type, vertex_name_t&gt;::type vertex_name_map_t;
typedef property_map_equivalent&lt;vertex_name_map_t, vertex_name_map_t&gt; vertex_comp_t;
vertex_comp_t vertex_comp =
make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2));
<em class="comment">// Create the vertex binary predicate</em>
typedef property_map&lt;graph_type, edge_name_t&gt;::type edge_name_map_t;
typedef property_map_equivalent&lt;edge_name_map_t, edge_name_map_t&gt; edge_comp_t;
edge_comp_t edge_comp =
make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2));
</pre>
<p>
Finally, a callback function object is created and the subgraph isomorphism mappings are
computed:
</p>
<pre>
<em class="comment">// Create callback</em>
vf2_print_callback&lt;graph_type, graph_type&gt; callback(graph1, graph2);
<em class="comment">
// Print out all subgraph isomorphism mappings between graph1 and graph2.
// Function vertex_order_by_mult is used to compute the order of
// vertices of graph1. This is the order in which the vertices are examined
// during the matching process.</em>
vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1),
edges_equivalent(edge_comp).vertices_equivalent(vertex_comp));
</pre>
<p>
For the complete example, see
<a href="../example/vf2_sub_graph_iso_multi_example.cpp">
<tt>examples/vf2_sub_graph_iso_multi_example.cpp</tt></a>.
<br>
</p>
<h3 id="notes">Notes</h3>
<p>
If the <tt>EdgeList</tt> allows for parallel edges, e.g. <tt>vecS</tt>, the
algorithm does some bookkeeping of already identified edges. Matched edges
are temporarily stored using <tt>std::set</tt> as container, requiring that
<tt>edge_descriptor</tt> are <a href="http://www.sgi.com/tech/stl/LessThanComparable.html">
LessThan Comparable</a>. In contrast, if instead you enforce the absence of
parallel edges, e.g. by using <tt>setS</tt>, the lookup function falls back
to <tt>edge()</tt> without performing any bookkeeping.
</p>
<h3>Bibliography</h3>
<dl>
<dt><a name="cordella2001">1</a></dt>
<dd>
L.&nbsp;P. Cordella, P. Foggia, C. Sansone, and M. Vento.
<br><em>An improved algorithm for matching large graphs</em>.
<br>In: 3rd IAPR-TC15 Workshop on Graph-based Representations in Pattern Recognition, pp. 149-159, Cuen, 2001.
<p></p>
</dd>
<dt><a name="cordella2004">2</a></dt>
<dd>
L.&nbsp;P. Cordella, P. Foggia, C. Sansone, and M. Vento.
<br><em>A (Sub)Graph Isomorphism Algorithm for Matching Large Graphs</em>.
<br>IEEE Trans. Pattern Anal. Mach. Intell., vol. 26, no. 10, pp. 1367-1372, 2004.
<p></p>
</dd>
<dt><a name="foggia_etal">3</a></dt>
<dd>
<a href="http://www.cs.sunysb.edu/~algorith/implement/vflib/implement.shtml">
<tt>http://www.cs.sunysb.edu/~algorith/implement/vflib/implement.shtml</tt></a>
<p></p>
</dd>
</dl>
<hr>
<p>
Copyright &copy; 2012, Flavio De Lorenzi
(<a href="mailto:fdlorenzi@gmail.com">fdlorenzi@gmail.com</a>)
</p>
</body>
</html>

View File

@@ -30,6 +30,7 @@ exe ospf-example : ospf-example.cpp ../build//boost_graph ;
# exe cc-internet : cc-internet.cpp ../build//boost_graph ;
exe implicit_graph : implicit_graph.cpp ;
exe astar_maze : astar_maze.cpp ;
exe astar-cities : astar-cities.cpp ;
exe stoer_wagner : stoer_wagner.cpp ;
exe bfs-example : bfs-example.cpp ;
exe bfs-example2 : bfs-example2.cpp ;
@@ -43,3 +44,6 @@ exe strong_components : strong_components.cpp ../build//boost_graph ;
exe strong-components : strong-components.cpp ;
exe subgraph : subgraph.cpp ;
exe subgraph_properties : subgraph_properties.cpp ;
exe vf2_sub_graph_iso_example : vf2_sub_graph_iso_example.cpp ;
exe vf2_sub_graph_iso_multi_example : vf2_sub_graph_iso_multi_example.cpp ;

View File

@@ -192,7 +192,7 @@ int main(int argc, char **argv)
vector<cost> d(num_vertices(g));
try {
// call astar named parameter interface
astar_search
astar_search_tree
(g, start,
distance_heuristic<mygraph_t, cost, location*>
(locations, goal),

View File

@@ -26,12 +26,12 @@ undirected_graph_demo1()
add_edge(zero, two, undigraph);
add_edge(one, two, undigraph);
std::cout << "out_edges(0): ";
std::cout << "out_edges(0):";
for (boost::tie(out, out_end) = out_edges(zero, undigraph); out != out_end; ++out)
std::cout << *out;
std::cout << std::endl << "in_edges(0): ";
std::cout << ' ' << *out;
std::cout << std::endl << "in_edges(0):";
for (boost::tie(in, in_end) = in_edges(zero, undigraph); in != in_end; ++in)
std::cout << *in;
std::cout << ' ' << *in;
std::cout << std::endl;
}
@@ -91,6 +91,14 @@ undirected_graph_demo2()
#endif
std::cout << "weight[(u,v)] = " << get(weight, e1) << std::endl;
std::cout << "weight[(v,u)] = " << get(weight, e2) << std::endl;
std::cout << "the edges incident to v: ";
typename boost::graph_traits<UndirectedGraph>::out_edge_iterator e, e_end;
typename boost::graph_traits<UndirectedGraph>::vertex_descriptor
s = vertex(0, undigraph);
for (boost::tie(e, e_end) = out_edges(s, undigraph); e != e_end; ++e)
std::cout << "(" << source(*e, undigraph)
<< "," << target(*e, undigraph) << ")" << std::endl;
}
@@ -103,7 +111,7 @@ main()
typedef adjacency_list < vecS, vecS, directedS,
no_property, Weight > DirectedGraph;
undirected_graph_demo1 < UndirectedGraph > ();
undirected_graph_demo2 < UndirectedGraph > ();
directed_graph_demo < DirectedGraph > ();
undirected_graph_demo2 < UndirectedGraph > ();
return 0;
}

View File

@@ -1,3 +1,5 @@
out_edges(0): (0,1) (0,2)
in_edges(0): (1,0) (2,0)
in a directed graph is (u,v) == (v,u) ? 0
weight[(u,v)] = 1.2
weight[(v,u)] = 2.4

View File

@@ -0,0 +1,40 @@
//=======================================================================
// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com)
//
// 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/adjacency_list.hpp>
#include <boost/graph/vf2_sub_graph_iso.hpp>
using namespace boost;
int main() {
typedef adjacency_list<setS, vecS, bidirectionalS> graph_type;
// Build graph1
int num_vertices1 = 8; graph_type graph1(num_vertices1);
add_edge(0, 6, graph1); add_edge(0, 7, graph1);
add_edge(1, 5, graph1); add_edge(1, 7, graph1);
add_edge(2, 4, graph1); add_edge(2, 5, graph1); add_edge(2, 6, graph1);
add_edge(3, 4, graph1);
// Build graph2
int num_vertices2 = 9; graph_type graph2(num_vertices2);
add_edge(0, 6, graph2); add_edge(0, 8, graph2);
add_edge(1, 5, graph2); add_edge(1, 7, graph2);
add_edge(2, 4, graph2); add_edge(2, 7, graph2); add_edge(2, 8, graph2);
add_edge(3, 4, graph2); add_edge(3, 5, graph2); add_edge(3, 6, graph2);
// Create callback to print mappings
vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);
// Print out all subgraph isomorphism mappings between graph1 and graph2.
// Vertices and edges are assumed to be always equivalent.
vf2_subgraph_iso(graph1, graph2, callback);
return 0;
}

View File

@@ -0,0 +1,89 @@
//=======================================================================
// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com)
//
// 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/adjacency_list.hpp>
#include <boost/graph/vf2_sub_graph_iso.hpp>
using namespace boost;
int main() {
typedef property<edge_name_t, char> edge_property;
typedef property<vertex_name_t, char, property<vertex_index_t, int> > vertex_property;
// Using a vecS graphs => the index maps are implicit.
typedef adjacency_list<vecS, vecS, bidirectionalS, vertex_property, edge_property> graph_type;
// Build graph1
graph_type graph1;
add_vertex(vertex_property('a'), graph1);
add_vertex(vertex_property('a'), graph1);
add_vertex(vertex_property('a'), graph1);
add_edge(0, 1, edge_property('b'), graph1);
add_edge(0, 1, edge_property('b'), graph1);
add_edge(0, 1, edge_property('d'), graph1);
add_edge(1, 2, edge_property('s'), graph1);
add_edge(2, 2, edge_property('l'), graph1);
add_edge(2, 2, edge_property('l'), graph1);
// Build graph2
graph_type graph2;
add_vertex(vertex_property('a'), graph2);
add_vertex(vertex_property('a'), graph2);
add_vertex(vertex_property('a'), graph2);
add_vertex(vertex_property('a'), graph2);
add_vertex(vertex_property('a'), graph2);
add_vertex(vertex_property('a'), graph2);
add_edge(0, 1, edge_property('a'), graph2);
add_edge(0, 1, edge_property('a'), graph2);
add_edge(0, 1, edge_property('b'), graph2);
add_edge(1, 2, edge_property('s'), graph2);
add_edge(2, 3, edge_property('b'), graph2);
add_edge(2, 3, edge_property('d'), graph2);
add_edge(2, 3, edge_property('b'), graph2);
add_edge(3, 4, edge_property('s'), graph2);
add_edge(4, 4, edge_property('l'), graph2);
add_edge(4, 4, edge_property('l'), graph2);
add_edge(4, 5, edge_property('c'), graph2);
add_edge(4, 5, edge_property('c'), graph2);
add_edge(4, 5, edge_property('c'), graph2);
add_edge(5, 0, edge_property('s'), graph2);
// create predicates
typedef property_map<graph_type, vertex_name_t>::type vertex_name_map_t;
typedef property_map_equivalent<vertex_name_map_t, vertex_name_map_t> vertex_comp_t;
vertex_comp_t vertex_comp =
make_property_map_equivalent(get(vertex_name, graph1), get(vertex_name, graph2));
typedef property_map<graph_type, edge_name_t>::type edge_name_map_t;
typedef property_map_equivalent<edge_name_map_t, edge_name_map_t> edge_comp_t;
edge_comp_t edge_comp =
make_property_map_equivalent(get(edge_name, graph1), get(edge_name, graph2));
// Create callback
vf2_print_callback<graph_type, graph_type> callback(graph1, graph2);
// Print out all subgraph isomorphism mappings between graph1 and graph2.
// Function vertex_order_by_mult is used to compute the order of
// vertices of graph1. This is the order in which the vertices are examined
// during the matching process.
vf2_subgraph_iso(graph1, graph2, callback, vertex_order_by_mult(graph1),
edges_equivalent(edge_comp).vertices_equivalent(vertex_comp));
return 0;
}

View File

@@ -188,6 +188,7 @@ namespace boost {
} // namespace detail
template <typename Selector> struct is_distributed_selector: mpl::false_ {};
//===========================================================================

View File

@@ -22,9 +22,12 @@
#include <boost/graph/relax.hpp>
#include <boost/graph/exception.hpp>
#include <boost/graph/breadth_first_search.hpp>
#include <boost/graph/iteration_macros.hpp>
#include <boost/graph/detail/d_ary_heap.hpp>
#include <boost/graph/property_maps/constant_property_map.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/property_map/vector_property_map.hpp>
#include <boost/property_map/function_property_map.hpp>
#include <boost/concept/assert.hpp>
namespace boost {
@@ -159,8 +162,9 @@ namespace boost {
template <class Edge, class Graph>
void tree_edge(Edge e, const Graph& g) {
using boost::get;
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
bool m_decreased =
relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if(m_decreased) {
m_vis.edge_relaxed(e, g);
@@ -175,8 +179,9 @@ namespace boost {
template <class Edge, class Graph>
void gray_target(Edge e, const Graph& g) {
using boost::get;
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
bool m_decreased =
relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if(m_decreased) {
put(m_cost, target(e, g),
@@ -192,8 +197,9 @@ namespace boost {
template <class Edge, class Graph>
void black_target(Edge e, const Graph& g) {
using boost::get;
m_decreased = relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
bool m_decreased =
relax(e, g, m_weight, m_predecessor, m_distance,
m_combine, m_compare);
if(m_decreased) {
m_vis.edge_relaxed(e, g);
@@ -219,7 +225,6 @@ namespace boost {
ColorMap m_color;
BinaryFunction m_combine;
BinaryPredicate m_compare;
bool m_decreased;
C m_zero;
};
@@ -263,6 +268,77 @@ namespace boost {
breadth_first_visit(g, s, Q, bfs_vis, color);
}
namespace graph_detail {
template <typename A, typename B>
struct select1st {
typedef std::pair<A, B> argument_type;
typedef A result_type;
A operator()(const std::pair<A, B>& p) const {return p.first;}
};
}
template <typename VertexListGraph, typename AStarHeuristic,
typename AStarVisitor, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap,
typename CompareFunction, typename CombineFunction,
typename CostInf, typename CostZero>
inline void
astar_search_no_init_tree
(const VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
CompareFunction compare, CombineFunction combine,
CostInf /*inf*/, CostZero zero)
{
typedef typename graph_traits<VertexListGraph>::vertex_descriptor
Vertex;
typedef typename property_traits<DistanceMap>::value_type Distance;
typedef d_ary_heap_indirect<
std::pair<Distance, Vertex>,
4,
null_property_map<std::pair<Distance, Vertex>, std::size_t>,
function_property_map<graph_detail::select1st<Distance, Vertex>, std::pair<Distance, Vertex> >,
CompareFunction>
MutableQueue;
MutableQueue Q(
make_function_property_map<std::pair<Distance, Vertex> >(graph_detail::select1st<Distance, Vertex>()),
null_property_map<std::pair<Distance, Vertex>, std::size_t>(),
compare);
vis.discover_vertex(s, g);
Q.push(std::make_pair(get(cost, s), s));
while (!Q.empty()) {
Vertex v;
Distance v_rank;
boost::tie(v_rank, v) = Q.top();
Q.pop();
vis.examine_vertex(v, g);
BGL_FORALL_OUTEDGES_T(v, e, g, VertexListGraph) {
Vertex w = target(e, g);
vis.examine_edge(e, g);
Distance e_weight = get(weight, e);
if (compare(e_weight, zero))
BOOST_THROW_EXCEPTION(negative_edge());
bool decreased =
relax(e, g, weight, predecessor, distance,
combine, compare);
Distance w_d = combine(get(distance, v), e_weight);
if (decreased) {
vis.edge_relaxed(e, g);
Distance w_rank = combine(get(distance, w), h(w));
put(cost, w, w_rank);
vis.discover_vertex(w, g);
Q.push(std::make_pair(w_rank, w));
} else {
vis.edge_not_relaxed(e, g);
}
}
vis.finish_vertex(v, g);
}
}
// Non-named parameter interface
template <typename VertexListGraph, typename AStarHeuristic,
@@ -303,6 +379,40 @@ namespace boost {
}
// Non-named parameter interface
template <typename VertexListGraph, typename AStarHeuristic,
typename AStarVisitor, typename PredecessorMap,
typename CostMap, typename DistanceMap,
typename WeightMap,
typename CompareFunction, typename CombineFunction,
typename CostInf, typename CostZero>
inline void
astar_search_tree
(const VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, AStarVisitor vis,
PredecessorMap predecessor, CostMap cost,
DistanceMap distance, WeightMap weight,
CompareFunction compare, CombineFunction combine,
CostInf inf, CostZero zero)
{
typename graph_traits<VertexListGraph>::vertex_iterator ui, ui_end;
for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) {
put(distance, *ui, inf);
put(cost, *ui, inf);
put(predecessor, *ui, *ui);
vis.initialize_vertex(*ui, g);
}
put(distance, s, zero);
put(cost, s, h(s));
astar_search_no_init_tree
(g, s, h, vis, predecessor, cost, distance, weight,
compare, combine, inf, zero);
}
// Named parameter interfaces
template <typename VertexListGraph,
typename AStarHeuristic,
@@ -345,6 +455,46 @@ namespace boost {
arg_pack[_distance_zero | D()]);
}
// Named parameter interfaces
template <typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R>
void
astar_search_tree
(const VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, const bgl_named_params<P, T, R>& params)
{
using namespace boost::graph::keywords;
typedef bgl_named_params<P, T, R> params_type;
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
// Distance type is the value type of the distance map if there is one,
// otherwise the value type of the weight map.
typedef
typename detail::override_const_property_result<
arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type
weight_map_type;
typedef typename boost::property_traits<weight_map_type>::value_type W;
typedef
typename detail::map_maker<VertexListGraph, arg_pack_type, tag::distance_map, W>::map_type
distance_map_type;
typedef typename boost::property_traits<distance_map_type>::value_type D;
const D inf = arg_pack[_distance_inf | (std::numeric_limits<D>::max)()];
astar_search_tree
(g, s, h,
arg_pack[_visitor | make_astar_visitor(null_visitor())],
arg_pack[_predecessor_map | dummy_property_map()],
detail::make_property_map_from_arg_pack_gen<tag::rank_map, D>(D())(g, arg_pack),
detail::make_property_map_from_arg_pack_gen<tag::distance_map, W>(W())(g, arg_pack),
detail::override_const_property(arg_pack, _weight_map, g, edge_weight),
arg_pack[_distance_compare | std::less<D>()],
arg_pack[_distance_combine | closed_plus<D>(inf)],
inf,
arg_pack[_distance_zero | D()]);
}
template <typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R>
@@ -378,6 +528,37 @@ namespace boost {
arg_pack[_distance_zero | D()]);
}
template <typename VertexListGraph,
typename AStarHeuristic,
typename P, typename T, typename R>
void
astar_search_no_init_tree
(const VertexListGraph &g,
typename graph_traits<VertexListGraph>::vertex_descriptor s,
AStarHeuristic h, const bgl_named_params<P, T, R>& params)
{
using namespace boost::graph::keywords;
typedef bgl_named_params<P, T, R> params_type;
BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params)
typedef
typename detail::override_const_property_result<
arg_pack_type, tag::weight_map, edge_weight_t, VertexListGraph>::type
weight_map_type;
typedef typename boost::property_traits<weight_map_type>::value_type D;
const D inf = arg_pack[_distance_inf | (std::numeric_limits<D>::max)()];
astar_search_no_init_tree
(g, s, h,
arg_pack[_visitor | make_astar_visitor(null_visitor())],
arg_pack[_predecessor_map | dummy_property_map()],
detail::make_property_map_from_arg_pack_gen<tag::rank_map, D>(D())(g, arg_pack),
detail::make_property_map_from_arg_pack_gen<tag::distance_map, D>(D())(g, arg_pack),
detail::override_const_property(arg_pack, _weight_map, g, edge_weight),
arg_pack[_distance_compare | std::less<D>()],
arg_pack[_distance_combine | closed_plus<D>(inf)],
inf,
arg_pack[_distance_zero | D()]);
}
} // namespace boost
#endif // BOOST_GRAPH_ASTAR_SEARCH_HPP

View File

@@ -442,11 +442,11 @@ class bk_max_flow {
for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
edge_descriptor in_edge = get(m_rev_edge_map, *ei);
vertex_descriptor other_node = source(in_edge, m_g);
if(get_tree(other_node) == tColorTraits::black() && has_parent(other_node)){
if(get_tree(other_node) == tColorTraits::black() && other_node != m_source){
if(get(m_res_cap_map, in_edge) > 0){
add_active_node(other_node);
}
if(source(get_edge_to_parent(other_node), m_g) == current_node){
if(has_parent(other_node) && source(get_edge_to_parent(other_node), m_g) == current_node){
//we are the parent of that node
//it has to find a new parent, too
set_no_parent(other_node);
@@ -483,11 +483,11 @@ class bk_max_flow {
for(boost::tie(ei, e_end) = out_edges(current_node, m_g); ei != e_end; ++ei){
const edge_descriptor out_edge = *ei;
const vertex_descriptor other_node = target(out_edge, m_g);
if(get_tree(other_node) == tColorTraits::white() && has_parent(other_node)){
if(get_tree(other_node) == tColorTraits::white() && other_node != m_sink){
if(get(m_res_cap_map, out_edge) > 0){
add_active_node(other_node);
}
if(target(get_edge_to_parent(other_node), m_g) == current_node){
if(has_parent(other_node) && target(get_edge_to_parent(other_node), m_g) == current_node){
//we were it's parent, so it has to find a new one, too
set_no_parent(other_node);
m_child_orphans.push(other_node);
@@ -526,6 +526,9 @@ class bk_max_flow {
inline void add_active_node(vertex_descriptor v){
BOOST_ASSERT(get_tree(v) != tColorTraits::gray());
if(get(m_in_active_list_map, v)){
if (m_last_grow_vertex == v) {
m_last_grow_vertex = graph_traits<Graph>::null_vertex();
}
return;
} else{
put(m_in_active_list_map, v, true);

View File

@@ -37,7 +37,9 @@
#include <boost/integer.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/mpl/if.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/graph/graph_selectors.hpp>
#include <boost/graph/detail/is_distributed_selector.hpp>
#include <boost/graph/properties.hpp>
#include <boost/static_assert.hpp>
#include <boost/functional/hash.hpp>
@@ -1322,8 +1324,9 @@ struct csr_property_map_helper<BOOST_CSR_GRAPH_TYPE, Tag, graph_property_tag> {
typedef transform_value_property_map<detail::lookup_one_property_f<const plist_type, Tag>, all_const_type> const_type;
};
// disable_if isn't truly necessary but required to avoid ambiguity with specializations below
template <BOOST_CSR_GRAPH_TEMPLATE_PARMS, typename Tag>
struct property_map<BOOST_CSR_GRAPH_TYPE, Tag>:
struct property_map<BOOST_CSR_GRAPH_TYPE, Tag, typename disable_if<detail::is_distributed_selector<Vertex> >::type>:
csr_property_map_helper<
BOOST_CSR_GRAPH_TYPE,
Tag,
@@ -1370,35 +1373,35 @@ put(Tag tag,
}
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
struct property_map<BOOST_CSR_GRAPH_TYPE, vertex_index_t>
struct property_map<BOOST_CSR_GRAPH_TYPE, vertex_index_t, typename disable_if<detail::is_distributed_selector<Vertex> >::type>
{
typedef typed_identity_property_map<Vertex> type;
typedef type const_type;
};
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
struct property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t>
struct property_map<BOOST_CSR_GRAPH_TYPE, edge_index_t, typename disable_if<detail::is_distributed_selector<Vertex> >::type>
{
typedef detail::csr_edge_index_map<Vertex, EdgeIndex> type;
typedef type const_type;
};
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
struct property_map<BOOST_CSR_GRAPH_TYPE, vertex_all_t>
struct property_map<BOOST_CSR_GRAPH_TYPE, vertex_all_t, typename disable_if<detail::is_distributed_selector<Vertex> >::type>
{
typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::vertex_map_type type;
typedef typename BOOST_CSR_GRAPH_TYPE::inherited_vertex_properties::const_vertex_map_type const_type;
};
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
struct property_map<BOOST_CSR_GRAPH_TYPE, edge_all_t>
struct property_map<BOOST_CSR_GRAPH_TYPE, edge_all_t, typename disable_if<detail::is_distributed_selector<Vertex> >::type>
{
typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::edge_map_type type;
typedef typename BOOST_CSR_GRAPH_TYPE::forward_type::inherited_edge_properties::const_edge_map_type const_type;
};
template<BOOST_CSR_GRAPH_TEMPLATE_PARMS>
struct property_map<BOOST_CSR_GRAPH_TYPE, graph_all_t>
struct property_map<BOOST_CSR_GRAPH_TYPE, graph_all_t, typename disable_if<detail::is_distributed_selector<Vertex> >::type>
{
typedef boost::ref_property_map<BOOST_CSR_GRAPH_TYPE*, typename BOOST_CSR_GRAPH_TYPE::graph_property_type> type;
typedef boost::ref_property_map<BOOST_CSR_GRAPH_TYPE*, const typename BOOST_CSR_GRAPH_TYPE::graph_property_type> const_type;

View File

@@ -309,14 +309,16 @@ namespace boost {
public:
typedef Property property_type;
inline stored_ra_edge_iter() { }
inline stored_ra_edge_iter(Vertex v, Iter i = Iter(),
EdgeVec* edge_vec = 0)
inline explicit stored_ra_edge_iter(Vertex v) // Only used for comparisons
: stored_edge<Vertex>(v), m_i(0), m_vec(0){ }
inline stored_ra_edge_iter(Vertex v, Iter i, EdgeVec* edge_vec)
: stored_edge<Vertex>(v), m_i(i - edge_vec->begin()), m_vec(edge_vec){ }
inline Property& get_property() { return (*m_vec)[m_i].get_property(); }
inline Property& get_property() { BOOST_ASSERT ((m_vec != 0)); return (*m_vec)[m_i].get_property(); }
inline const Property& get_property() const {
BOOST_ASSERT ((m_vec != 0));
return (*m_vec)[m_i].get_property();
}
inline Iter get_iter() const { return m_vec->begin() + m_i; }
inline Iter get_iter() const { BOOST_ASSERT ((m_vec != 0)); return m_vec->begin() + m_i; }
protected:
std::size_t m_i;
EdgeVec* m_vec;

View File

@@ -126,18 +126,21 @@ namespace boost {
}
Value& top() {
BOOST_ASSERT (!this->empty());
return data[0];
}
const Value& top() const {
BOOST_ASSERT (!this->empty());
return data[0];
}
void pop() {
BOOST_ASSERT (!this->empty());
put(index_in_heap, data[0], (size_type)(-1));
if (data.size() != 1) {
data[0] = data.back();
put(index_in_heap, data[0], 0);
put(index_in_heap, data[0], (size_type)(0));
data.pop_back();
preserve_heap_property_down();
verify_heap();

View File

@@ -0,0 +1,26 @@
// Copyright 2012 The Trustees of Indiana University.
// 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)
// Authors: Jeremiah Willcock
// Andrew Lumsdaine
// Selector to determine whether a selector is distributedS (can only be true
// if <boost/graph/distributed/selector.hpp> has been included) so that we can
// disable various sequential-graph-only traits specializations for distributed
// graphs.
#ifndef BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP
#define BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP
#include <boost/mpl/bool.hpp>
namespace boost {
namespace detail {
template <typename> struct is_distributed_selector: boost::mpl::false_ {};
}
}
#endif // BOOST_GRAPH_DETAIL_IS_DISTRIBUTED_SELECTOR_HPP

View File

@@ -218,9 +218,9 @@ namespace graph_detail {
#define LABELED_GRAPH_PARAMS typename G, typename L, typename S
#define LABELED_GRAPH labeled_graph<G,L,S>
// Specialize mutability traits for for the labeled graph.
// Specialize mutability traits for the labeled graph.
// This specialization depends on the mutability of the underlying graph type.
// If the underlying graph is fully mutable, this this is also fully mutable.
// If the underlying graph is fully mutable, this is also fully mutable.
// Otherwise, it's different.
template <LABELED_GRAPH_PARAMS>
struct graph_mutability_traits< LABELED_GRAPH > {

View File

@@ -113,16 +113,17 @@ namespace boost {
distance_weight_combine, distance_compare);
if (was_edge_relaxed) {
vertex_queue.update(neighbor_vertex);
visitor.edge_relaxed(current_edge, graph);
if (is_neighbor_undiscovered) {
visitor.discover_vertex(neighbor_vertex, graph);
vertex_queue.push(neighbor_vertex);
} else {
vertex_queue.update(neighbor_vertex);
}
} else {
visitor.edge_not_relaxed(current_edge, graph);
}
if (is_neighbor_undiscovered) {
visitor.discover_vertex(neighbor_vertex, graph);
vertex_queue.push(neighbor_vertex);
}
} // end out edge iteration
visitor.finish_vertex(min_vertex, graph);

View File

@@ -9,6 +9,10 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/pending/property.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
namespace boost
{
@@ -27,8 +31,8 @@ struct directed_graph_tag { };
*/
template <
typename VertexProp = no_property,
typename EdgeProp= no_property,
typename GraphProp= no_property>
typename EdgeProp = no_property,
typename GraphProp = no_property>
class directed_graph
{
public:
@@ -39,15 +43,14 @@ public:
typedef typename lookup_one_property<VertexProp, vertex_bundle_t>::type vertex_bundled;
typedef typename lookup_one_property<EdgeProp, edge_bundle_t>::type edge_bundled;
private:
// Wrap the user-specified properties with an index.
typedef property<vertex_index_t, unsigned, vertex_property_type> vertex_property;
typedef property<edge_index_t, unsigned, edge_property_type> edge_property;
public:
// Embed indices into the vertex type.
typedef property<vertex_index_t, unsigned, vertex_property_type> internal_vertex_property;
typedef property<edge_index_t, unsigned, edge_property_type> internal_edge_property;
public:
typedef adjacency_list<
listS, listS, bidirectionalS,
vertex_property, edge_property, GraphProp,
internal_vertex_property, internal_edge_property, GraphProp,
listS
> graph_type;
@@ -80,8 +83,8 @@ public:
typedef typename graph_type::edge_parallel_category edge_parallel_category;
typedef typename graph_type::traversal_category traversal_category;
typedef unsigned vertex_index_type;
typedef unsigned edge_index_type;
typedef std::size_t vertex_index_type;
typedef std::size_t edge_index_type;
directed_graph(GraphProp const& p = GraphProp())
: m_graph(p), m_num_vertices(0), m_num_edges(0), m_max_vertex_index(0)
@@ -137,6 +140,7 @@ public:
vertices_size_type num_vertices() const
{ return m_num_vertices; }
private:
// This helper function manages the attribution of vertex indices.
vertex_descriptor make_index(vertex_descriptor v) {
@@ -150,7 +154,7 @@ public:
{ return make_index(boost::add_vertex(m_graph)); }
vertex_descriptor add_vertex(vertex_property_type const& p)
{ return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); }
{ return make_index(boost::add_vertex(internal_vertex_property(0u, p), m_graph)); }
void clear_vertex(vertex_descriptor v)
{
@@ -186,7 +190,7 @@ public:
std::pair<edge_descriptor, bool>
add_edge(vertex_descriptor u, vertex_descriptor v, edge_property_type const& p)
{ return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); }
{ return make_index(boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); }
void remove_edge(vertex_descriptor u, vertex_descriptor v)
{
@@ -516,37 +520,32 @@ remove_in_edge_if(typename DIRECTED_GRAPH::vertex_descriptor v,
DIRECTED_GRAPH& g)
{ return remove_in_edge_if(v, pred, g.impl()); }
// Helper code for working with property maps
namespace detail
{
struct directed_graph_vertex_property_selector {
template <class DirectedGraph, class Property, class Tag>
struct bind_ {
typedef typename DirectedGraph::graph_type Graph;
typedef property_map<Graph, Tag> PropertyMap;
typedef typename PropertyMap::type type;
typedef typename PropertyMap::const_type const_type;
};
};
template <DIRECTED_GRAPH_PARAMS, typename Property>
struct property_map<DIRECTED_GRAPH, Property>: property_map<typename DIRECTED_GRAPH::graph_type, Property> {};
struct directed_graph_edge_property_selector {
template <class DirectedGraph, class Property, class Tag>
struct bind_ {
typedef typename DirectedGraph::graph_type Graph;
typedef property_map<Graph, Tag> PropertyMap;
typedef typename PropertyMap::type type;
typedef typename PropertyMap::const_type const_type;
};
};
}
template <DIRECTED_GRAPH_PARAMS>
struct property_map<DIRECTED_GRAPH, vertex_all_t> {
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename DIRECTED_GRAPH::graph_type, vertex_all_t>::const_type>
const_type;
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename DIRECTED_GRAPH::graph_type, vertex_all_t>::type>
type;
};
template <>
struct vertex_property_selector<directed_graph_tag>
{ typedef detail::directed_graph_vertex_property_selector type; };
template <>
struct edge_property_selector<directed_graph_tag>
{ typedef detail::directed_graph_edge_property_selector type; };
template <DIRECTED_GRAPH_PARAMS>
struct property_map<DIRECTED_GRAPH, edge_all_t> {
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename DIRECTED_GRAPH::graph_type, edge_all_t>::const_type>
const_type;
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename DIRECTED_GRAPH::graph_type, edge_all_t>::type>
type;
};
// PropertyGraph concepts
template <DIRECTED_GRAPH_PARAMS, typename Property>
@@ -559,6 +558,26 @@ inline typename property_map<DIRECTED_GRAPH, Property>::const_type
get(Property p, DIRECTED_GRAPH const& g)
{ return get(p, g.impl()); }
template <DIRECTED_GRAPH_PARAMS>
inline typename property_map<DIRECTED_GRAPH, vertex_all_t>::type
get(vertex_all_t, DIRECTED_GRAPH& g)
{ return typename property_map<DIRECTED_GRAPH, vertex_all_t>::type(detail::remove_first_property(), get(vertex_all, g.impl())); }
template <DIRECTED_GRAPH_PARAMS>
inline typename property_map<DIRECTED_GRAPH, vertex_all_t>::const_type
get(vertex_all_t, DIRECTED_GRAPH const& g)
{ return typename property_map<DIRECTED_GRAPH, vertex_all_t>::const_type(detail::remove_first_property(), get(vertex_all, g.impl())); }
template <DIRECTED_GRAPH_PARAMS>
inline typename property_map<DIRECTED_GRAPH, edge_all_t>::type
get(edge_all_t, DIRECTED_GRAPH& g)
{ return typename property_map<DIRECTED_GRAPH, edge_all_t>::type(detail::remove_first_property(), get(edge_all, g.impl())); }
template <DIRECTED_GRAPH_PARAMS>
inline typename property_map<DIRECTED_GRAPH, edge_all_t>::const_type
get(edge_all_t, DIRECTED_GRAPH const& g)
{ return typename property_map<DIRECTED_GRAPH, edge_all_t>::const_type(detail::remove_first_property(), get(edge_all, g.impl())); }
template <DIRECTED_GRAPH_PARAMS, typename Property, typename Key>
inline typename property_traits<
typename property_map<
@@ -568,10 +587,40 @@ inline typename property_traits<
get(Property p, DIRECTED_GRAPH const& g, Key const& k)
{ return get(p, g.impl(), k); }
template <DIRECTED_GRAPH_PARAMS, typename Key>
inline typename property_traits<
typename property_map<
typename DIRECTED_GRAPH::graph_type, vertex_all_t
>::const_type
>::value_type
get(vertex_all_t, DIRECTED_GRAPH const& g, Key const& k)
{ return get(vertex_all, g.impl(), k).m_base; }
template <DIRECTED_GRAPH_PARAMS, typename Key>
inline typename property_traits<
typename property_map<
typename DIRECTED_GRAPH::graph_type, edge_all_t
>::const_type
>::value_type
get(edge_all_t, DIRECTED_GRAPH const& g, Key const& k)
{ return get(edge_all, g.impl(), k).m_base; }
template <DIRECTED_GRAPH_PARAMS, typename Property, typename Key, typename Value>
inline void put(Property p, DIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(p, g.impl(), k, v); }
template <DIRECTED_GRAPH_PARAMS, typename Key, typename Value>
inline void put(vertex_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(vertex_all, g.impl(), k,
typename DIRECTED_GRAPH::internal_vertex_property(get(vertex_index, g.impl(), k), v));
}
template <DIRECTED_GRAPH_PARAMS, typename Key, typename Value>
inline void put(edge_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(edge_all, g.impl(), k,
typename DIRECTED_GRAPH::internal_vertex_property(get(edge_index, g.impl(), k), v));
}
template <DIRECTED_GRAPH_PARAMS, class Property>
typename graph_property<DIRECTED_GRAPH, Property>::type&
get_property(DIRECTED_GRAPH& g, Property p)

View File

@@ -20,6 +20,9 @@
#include <boost/graph/numeric_values.hpp>
#include <boost/graph/buffer_concepts.hpp>
#include <boost/concept_check.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/mpl/not.hpp>
#include <boost/static_assert.hpp>
#include <boost/detail/workaround.hpp>
#include <boost/concept/assert.hpp>
@@ -55,12 +58,10 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
BOOST_concept(Graph,(G))
{
typedef typename graph_traits<G>::vertex_descriptor vertex_descriptor;
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::directed_category directed_category;
typedef typename graph_traits<G>::edge_parallel_category
edge_parallel_category;
typedef typename graph_traits<G>::traversal_category
traversal_category;
typedef typename graph_traits<G>::edge_parallel_category edge_parallel_category;
typedef typename graph_traits<G>::traversal_category traversal_category;
BOOST_CONCEPT_USAGE(Graph)
{
@@ -75,11 +76,12 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
: Graph<G>
{
typedef typename graph_traits<G>::edge_descriptor edge_descriptor;
typedef typename graph_traits<G>::out_edge_iterator
out_edge_iterator;
typedef typename graph_traits<G>::out_edge_iterator out_edge_iterator;
typedef typename graph_traits<G>::degree_size_type degree_size_type;
typedef typename graph_traits<G>::traversal_category traversal_category;
typedef typename graph_traits<G>::traversal_category
traversal_category;
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<out_edge_iterator, void> >::value));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<degree_size_type, void> >::value));
BOOST_CONCEPT_USAGE(IncidenceGraph) {
BOOST_CONCEPT_ASSERT((MultiPassInputIterator<out_edge_iterator>));
@@ -123,6 +125,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
bidirectional_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<in_edge_iterator, void> >::value));
p = in_edges(v, g);
n = in_degree(v, g);
e = *p.first;
@@ -153,6 +157,8 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
adjacency_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<adjacency_iterator, void> >::value));
p = adjacent_vertices(v, g);
v = *p.first;
const_constraints(g);
@@ -178,6 +184,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
vertex_list_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<vertex_iterator, void> >::value));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<vertices_size_type, void> >::value));
#ifdef BOOST_VECTOR_AS_GRAPH_GRAPH_ADL_HACK
// dwa 2003/7/11 -- This clearly shouldn't be necessary, but if
// you want to use vector_as_graph, it is! I'm sure the graph
@@ -227,6 +236,9 @@ typename T::ThereReallyIsNoMemberByThisNameInT vertices(T const&);
BOOST_CONCEPT_ASSERT((Convertible<traversal_category,
edge_list_graph_tag>));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<edge_iterator, void> >::value));
BOOST_STATIC_ASSERT((boost::mpl::not_<boost::is_same<edges_size_type, void> >::value));
p = edges(g);
e = *p.first;
u = source(e, g);

View File

@@ -20,6 +20,7 @@
#include <boost/mpl/not.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/void.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/iterator/iterator_categories.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
@@ -28,23 +29,47 @@
namespace boost {
namespace detail {
#define BOOST_GRAPH_MEMBER_OR_VOID(name) \
BOOST_MPL_HAS_XXX_TRAIT_DEF(name) \
template <typename T> struct BOOST_JOIN(get_member_, name) {typedef typename T::name type;}; \
template <typename T> struct BOOST_JOIN(get_opt_member_, name): \
boost::mpl::eval_if_c< \
BOOST_JOIN(has_, name)<T>::value, \
BOOST_JOIN(get_member_, name)<T>, \
boost::mpl::identity<void> > \
{};
BOOST_GRAPH_MEMBER_OR_VOID(adjacency_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(out_edge_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(in_edge_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(vertex_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(edge_iterator)
BOOST_GRAPH_MEMBER_OR_VOID(vertices_size_type)
BOOST_GRAPH_MEMBER_OR_VOID(edges_size_type)
BOOST_GRAPH_MEMBER_OR_VOID(degree_size_type)
}
template <typename G>
struct graph_traits {
#define BOOST_GRAPH_PULL_OPT_MEMBER(name) \
typedef typename detail::BOOST_JOIN(get_opt_member_, name)<G>::type name;
typedef typename G::vertex_descriptor vertex_descriptor;
typedef typename G::edge_descriptor edge_descriptor;
typedef typename G::adjacency_iterator adjacency_iterator;
typedef typename G::out_edge_iterator out_edge_iterator;
typedef typename G::in_edge_iterator in_edge_iterator;
typedef typename G::vertex_iterator vertex_iterator;
typedef typename G::edge_iterator edge_iterator;
BOOST_GRAPH_PULL_OPT_MEMBER(adjacency_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(out_edge_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(in_edge_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(vertex_iterator)
BOOST_GRAPH_PULL_OPT_MEMBER(edge_iterator)
typedef typename G::directed_category directed_category;
typedef typename G::edge_parallel_category edge_parallel_category;
typedef typename G::traversal_category traversal_category;
typedef typename G::vertices_size_type vertices_size_type;
typedef typename G::edges_size_type edges_size_type;
typedef typename G::degree_size_type degree_size_type;
BOOST_GRAPH_PULL_OPT_MEMBER(vertices_size_type)
BOOST_GRAPH_PULL_OPT_MEMBER(edges_size_type)
BOOST_GRAPH_PULL_OPT_MEMBER(degree_size_type)
#undef BOOST_GRAPH_PULL_OPT_MEMBER
static inline vertex_descriptor null_vertex();
};

View File

@@ -204,14 +204,14 @@ template<typename MutableGraph>
const char* mutate_graph_impl<MutableGraph>::m_type_names[] = {"boolean", "int", "long", "float", "double", "string"};
void BOOST_GRAPH_DECL
read_graphml(std::istream& in, mutate_graph& g);
read_graphml(std::istream& in, mutate_graph& g, size_t desired_idx);
template<typename MutableGraph>
void
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp)
read_graphml(std::istream& in, MutableGraph& g, dynamic_properties& dp, size_t desired_idx = 0)
{
mutate_graph_impl<MutableGraph> mg(g,dp);
read_graphml(in, mg);
read_graphml(in, mg, desired_idx);
}
template <typename Types>

View File

@@ -475,12 +475,12 @@ namespace boost {
* from every vertex to every other vertex, which is computed in the
* first stages of the algorithm. This value's type must be a model
* of BasicMatrix with value type equal to the value type of the
* weight map. The default is a a vector of vectors.
* weight map. The default is a vector of vectors.
*
* \param spring_strength (UTIL/OUT) will be used to store the
* strength of the spring between every pair of vertices. This
* value's type must be a model of BasicMatrix with value type equal
* to the value type of the weight map. The default is a a vector of
* to the value type of the weight map. The default is a vector of
* vectors.
*
* \param partial_derivatives (UTIL) will be used to store the

View File

@@ -21,7 +21,7 @@
#include <boost/graph/graph_traits.hpp>
// This file implements a utility for creating mappings from arbitrary
// identifers to the vertices of a graph.
// identifiers to the vertices of a graph.
namespace boost {
@@ -104,7 +104,7 @@ namespace graph_detail {
// Tag dispatch on random access containers (i.e., vectors). This function
// basically requires a) that Container is vector<Label> and that Label
// is an unsigned integral value. Note that this will resize the vector
// to accomodate indices.
// to accommodate indices.
template <typename Container, typename Graph, typename Label, typename Prop>
std::pair<typename graph_traits<Graph>::vertex_descriptor, bool>
insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p,
@@ -112,7 +112,7 @@ namespace graph_detail {
{
typedef typename graph_traits<Graph>::vertex_descriptor Vertex;
// If the label is out of bounds, resize the vector to accomodate.
// If the label is out of bounds, resize the vector to accommodate.
// Resize by 2x the index so we don't cause quadratic insertions over
// time.
if(l >= c.size()) {
@@ -140,7 +140,7 @@ namespace graph_detail {
// Tag dispatch on unique associative containers (i.e. maps).
template <typename Container, typename Graph, typename Label, typename Prop>
std::pair<typename graph_traits<Graph>::vertex_descriptor, bool>
insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const&,
insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p,
unique_associative_container_tag)
{
// Here, we actually have to try the insertion first, and only add
@@ -150,6 +150,7 @@ namespace graph_detail {
std::pair<Iterator, bool> x = c.insert(std::make_pair(l, Vertex()));
if(x.second) {
x.first->second = add_vertex(g);
put(boost::vertex_all, g, x.first->second, p);
}
return std::make_pair(x.first->second, x.second);
}
@@ -246,7 +247,7 @@ struct labeled_graph_types {
* vertex labels and vertex descriptors.
*
* @todo This class is somewhat redundant for adjacency_list<*, vecS> if
* the intended label is an unsigned int (and perhpahs some other cases), but
* the intended label is an unsigned int (and perhaps some other cases), but
* it does avoid some weird ambiguities (i.e. adding a vertex with a label that
* does not match its target index).
*
@@ -310,7 +311,7 @@ public:
_map.insert(_map.end(), rng.first, rng.second);
}
// Construct a grpah over n vertices, each of which receives a label from
// Construct a graph over n vertices, each of which receives a label from
// the range [l, l + n). Note that the graph is not directly constructed
// over the n vertices, but added sequentially. This constructor is
// necessarily slower than the underlying counterpart.
@@ -544,8 +545,9 @@ inline bool label_vertex(typename LABELED_GRAPH::vertex_descriptor v,
{ return g.label_vertex(v, l); }
template <LABELED_GRAPH_PARAMS>
inline bool vertex_by_label(typename LABELED_GRAPH::label_type const l,
LABELED_GRAPH& g)
inline typename LABELED_GRAPH::vertex_descriptor
vertex_by_label(typename LABELED_GRAPH::label_type const l,
LABELED_GRAPH& g)
{ return g.vertex(l); }
//@}

View File

@@ -216,7 +216,7 @@ namespace boost
// Create tour using a preorder traversal of the mst
vector<Node> tour;
PreorderTraverser<Node, Tree> tvis(tour);
traverse_tree(0, t, tvis);
traverse_tree(indexmap[start], t, tvis);
pair<GVItr, GVItr> g_verts(vertices(g));
for(PreorderTraverser<Node, Tree>::const_iterator curr(tvis.begin());
@@ -228,7 +228,7 @@ namespace boost
}
// Connect back to the start of the tour
vis.visit_vertex(*g_verts.first, g);
vis.visit_vertex(start, g);
}
// Default tsp tour visitor that puts the tour in an OutputIterator

View File

@@ -11,14 +11,23 @@
#define BOOST_GRAPH_NAMED_GRAPH_HPP
#include <boost/config.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/functional/hash.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/member.hpp>
#include <boost/multi_index_container.hpp>
#include <boost/optional.hpp>
#include <boost/pending/property.hpp> // for boost::lookup_one_property
#include <boost/throw_exception.hpp>
#include <boost/tuple/tuple.hpp> // for boost::make_tuple
#include <boost/type_traits/is_same.hpp>
#include <boost/type_traits/remove_cv.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/utility/enable_if.hpp>
#include <functional> // for std::equal_to
#include <stdexcept> // for std::runtime_error
#include <utility> // for std::pair
namespace boost { namespace graph {
@@ -352,8 +361,15 @@ find_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name,
/// Retrieve the vertex associated with the given name, or add a new
/// vertex with that name if no such vertex is available.
/// Note: This is enabled only when the vertex property type is different
/// from the vertex name to avoid ambiguous overload problems with
/// the add_vertex() function that takes a vertex property.
template<BGL_NAMED_GRAPH_PARAMS>
Vertex
typename disable_if<is_same<
typename BGL_NAMED_GRAPH::vertex_name_type,
VertexProperty
>,
Vertex>::type
add_vertex(typename BGL_NAMED_GRAPH::vertex_name_type const& name,
BGL_NAMED_GRAPH& g)
{
@@ -401,6 +417,35 @@ add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
g.derived());
}
// Overloads to support EdgeMutablePropertyGraph graphs
template <BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_descriptor const& u,
typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
typename edge_property_type<Graph>::type const& p,
BGL_NAMED_GRAPH& g) {
return add_edge(u, add_vertex(v_name, g.derived()), p, g.derived());
}
template <BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
typename BGL_NAMED_GRAPH::vertex_descriptor const& v,
typename edge_property_type<Graph>::type const& p,
BGL_NAMED_GRAPH& g) {
return add_edge(add_vertex(u_name, g.derived()), v, p, g.derived());
}
template <BGL_NAMED_GRAPH_PARAMS>
std::pair<typename graph_traits<Graph>::edge_descriptor, bool>
add_edge(typename BGL_NAMED_GRAPH::vertex_name_type const& u_name,
typename BGL_NAMED_GRAPH::vertex_name_type const& v_name,
typename edge_property_type<Graph>::type const& p,
BGL_NAMED_GRAPH& g) {
return add_edge(add_vertex(u_name, g.derived()),
add_vertex(v_name, g.derived()), p, g.derived());
}
#undef BGL_NAMED_GRAPH
#undef BGL_NAMED_GRAPH_PARAMS

View File

@@ -224,7 +224,7 @@ namespace boost {
{};
} // namespace detail
template <class Graph, class Property>
template <class Graph, class Property, class Enable = void>
struct property_map:
mpl::if_<
is_same<typename detail::property_kind_from_graph<Graph, Property>::type, edge_property_tag>,
@@ -248,8 +248,8 @@ namespace boost {
>::type type;
};
template <class Graph> class vertex_property: vertex_property_type<Graph> {};
template <class Graph> class edge_property: edge_property_type<Graph> {};
template <typename Graph> struct vertex_property: vertex_property_type<Graph> {};
template <typename Graph> struct edge_property: edge_property_type<Graph> {};
template <typename Graph>
class degree_property_map

View File

@@ -54,6 +54,39 @@ inline constant_property_map<Key, Value>
make_constant_property(const Value& value)
{ return constant_property_map<Key, Value>(value); }
/**
* Same as above, but pretends to be writable as well.
*/
template <typename Key, typename Value>
struct constant_writable_property_map {
typedef Key key_type;
typedef Value value_type;
typedef Value& reference;
typedef boost::read_write_property_map_tag category;
constant_writable_property_map()
: m_value()
{ }
constant_writable_property_map(const value_type &value)
: m_value(value)
{ }
constant_writable_property_map(const constant_writable_property_map& copy)
: m_value(copy.m_value)
{ }
friend Value get(const constant_writable_property_map& me, Key) {return me.m_value;}
friend void put(const constant_writable_property_map&, Key, Value) {}
value_type m_value;
};
template <typename Key, typename Value>
inline constant_writable_property_map<Key, Value>
make_constant_writable_property(const Value& value)
{ return constant_writable_property_map<Key, Value>(value); }
} /* namespace boost */
#endif

View File

@@ -433,7 +433,7 @@ namespace detail {
{
return m[k];
}
};
}
template <class E>
struct property_traits<detail::underlying_edge_desc_map_type<E> > {

View File

@@ -64,7 +64,7 @@ namespace boost
// basically modernized it to use real data structures (no more arrays and matrices).
// Oh... and there's explicit control structures - not just gotos.
//
// The problem is definitely NP-complete, an an unbounded implementation of this
// The problem is definitely NP-complete, an unbounded implementation of this
// will probably run for quite a while on a large graph. The conclusions
// of this paper also reference a Paton algorithm for undirected graphs as being
// much more efficient (apparently based on spanning trees). Although not implemented,
@@ -85,7 +85,7 @@ namespace boost
// }
/**
* The default cycle visitor providse an empty visit function for cycle
* The default cycle visitor provides an empty visit function for cycle
* visitors.
*/
struct cycle_visitor
@@ -168,7 +168,7 @@ namespace detail
// conditions for allowing a traversal along this edge are:
// 1. the index of v must be greater than that at which the
// the path is rooted (p.front()).
// path is rooted (p.front()).
// 2. the vertex v cannot already be in the path
// 3. the vertex v cannot be closed to the vertex u

View File

@@ -9,6 +9,10 @@
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/properties.hpp>
#include <boost/pending/property.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/type_traits.hpp>
#include <boost/mpl/if.hpp>
namespace boost
{
@@ -39,16 +43,16 @@ public:
typedef typename lookup_one_property<VertexProp, vertex_bundle_t>::type vertex_bundled;
typedef typename lookup_one_property<EdgeProp, edge_bundle_t>::type edge_bundled;
private:
public:
// Embed indices into the vertex type.
typedef property<vertex_index_t, unsigned, vertex_property_type> vertex_property;
typedef property<edge_index_t, unsigned, edge_property_type> edge_property;
typedef property<vertex_index_t, unsigned, vertex_property_type> internal_vertex_property;
typedef property<edge_index_t, unsigned, edge_property_type> internal_edge_property;
public:
typedef adjacency_list<listS,
listS,
undirectedS,
vertex_property,
edge_property,
internal_vertex_property,
internal_edge_property,
GraphProp,
listS> graph_type;
private:
@@ -151,7 +155,7 @@ public:
{ return make_index(boost::add_vertex(m_graph)); }
vertex_descriptor add_vertex(vertex_property_type const& p)
{ return make_index(boost::add_vertex(vertex_property(0u, p), m_graph)); }
{ return make_index(boost::add_vertex(internal_vertex_property(0u, p), m_graph)); }
void clear_vertex(vertex_descriptor v) {
std::pair<out_edge_iterator, out_edge_iterator>
@@ -188,7 +192,7 @@ public:
std::pair<edge_descriptor, bool>
add_edge(vertex_descriptor u, vertex_descriptor v,
edge_property_type const& p)
{ return make_index(boost::add_edge(u, v, edge_property(0u, p), m_graph)); }
{ return make_index(boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); }
void remove_edge(vertex_descriptor u, vertex_descriptor v) {
// find all edges, (u, v)
@@ -525,6 +529,30 @@ remove_in_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v,
template <UNDIRECTED_GRAPH_PARAMS, typename Property>
struct property_map<UNDIRECTED_GRAPH, Property>: property_map<typename UNDIRECTED_GRAPH::graph_type, Property> {};
template <UNDIRECTED_GRAPH_PARAMS>
struct property_map<UNDIRECTED_GRAPH, vertex_all_t> {
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename UNDIRECTED_GRAPH::graph_type, vertex_all_t>::const_type>
const_type;
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename UNDIRECTED_GRAPH::graph_type, vertex_all_t>::type>
type;
};
template <UNDIRECTED_GRAPH_PARAMS>
struct property_map<UNDIRECTED_GRAPH, edge_all_t> {
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename UNDIRECTED_GRAPH::graph_type, edge_all_t>::const_type>
const_type;
typedef transform_value_property_map<
detail::remove_first_property,
typename property_map<typename UNDIRECTED_GRAPH::graph_type, edge_all_t>::type>
type;
};
// PropertyGraph concepts
template <UNDIRECTED_GRAPH_PARAMS, typename Property>
inline typename property_map<UNDIRECTED_GRAPH, Property>::type
@@ -536,6 +564,26 @@ inline typename property_map<UNDIRECTED_GRAPH, Property>::const_type
get(Property p, UNDIRECTED_GRAPH const& g)
{ return get(p, g.impl()); }
template <UNDIRECTED_GRAPH_PARAMS>
inline typename property_map<UNDIRECTED_GRAPH, vertex_all_t>::type
get(vertex_all_t, UNDIRECTED_GRAPH& g)
{ return typename property_map<UNDIRECTED_GRAPH, vertex_all_t>::type(detail::remove_first_property(), get(vertex_all, g.impl())); }
template <UNDIRECTED_GRAPH_PARAMS>
inline typename property_map<UNDIRECTED_GRAPH, vertex_all_t>::const_type
get(vertex_all_t, UNDIRECTED_GRAPH const& g)
{ return typename property_map<UNDIRECTED_GRAPH, vertex_all_t>::const_type(detail::remove_first_property(), get(vertex_all, g.impl())); }
template <UNDIRECTED_GRAPH_PARAMS>
inline typename property_map<UNDIRECTED_GRAPH, edge_all_t>::type
get(edge_all_t, UNDIRECTED_GRAPH& g)
{ return typename property_map<UNDIRECTED_GRAPH, edge_all_t>::type(detail::remove_first_property(), get(edge_all, g.impl())); }
template <UNDIRECTED_GRAPH_PARAMS>
inline typename property_map<UNDIRECTED_GRAPH, edge_all_t>::const_type
get(edge_all_t, UNDIRECTED_GRAPH const& g)
{ return typename property_map<UNDIRECTED_GRAPH, edge_all_t>::const_type(detail::remove_first_property(), get(edge_all, g.impl())); }
template <UNDIRECTED_GRAPH_PARAMS, typename Property, typename Key>
inline typename property_traits<
typename property_map<
@@ -545,10 +593,40 @@ inline typename property_traits<
get(Property p, UNDIRECTED_GRAPH const& g, Key const& k)
{ return get(p, g.impl(), k); }
template <UNDIRECTED_GRAPH_PARAMS, typename Key>
inline typename property_traits<
typename property_map<
typename UNDIRECTED_GRAPH::graph_type, vertex_all_t
>::const_type
>::value_type
get(vertex_all_t, UNDIRECTED_GRAPH const& g, Key const& k)
{ return get(vertex_all, g.impl(), k).m_base; }
template <UNDIRECTED_GRAPH_PARAMS, typename Key>
inline typename property_traits<
typename property_map<
typename UNDIRECTED_GRAPH::graph_type, edge_all_t
>::const_type
>::value_type
get(edge_all_t, UNDIRECTED_GRAPH const& g, Key const& k)
{ return get(edge_all, g.impl(), k).m_base; }
template <UNDIRECTED_GRAPH_PARAMS, typename Property, typename Key, typename Value>
inline void put(Property p, UNDIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(p, g.impl(), k, v); }
template <UNDIRECTED_GRAPH_PARAMS, typename Key, typename Value>
inline void put(vertex_all_t, UNDIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(vertex_all, g.impl(), k,
typename UNDIRECTED_GRAPH::internal_vertex_property(get(vertex_index, g.impl(), k), v));
}
template <UNDIRECTED_GRAPH_PARAMS, typename Key, typename Value>
inline void put(edge_all_t, UNDIRECTED_GRAPH& g, Key const& k, Value const& v)
{ put(edge_all, g.impl(), k,
typename UNDIRECTED_GRAPH::internal_vertex_property(get(edge_index, g.impl(), k), v));
}
template <UNDIRECTED_GRAPH_PARAMS, class Property>
inline typename graph_property<UNDIRECTED_GRAPH, Property>::type&
get_property(UNDIRECTED_GRAPH& g, Property p)

File diff suppressed because it is too large Load Diff

View File

@@ -244,6 +244,27 @@ namespace boost {
} // namespace detail
namespace detail {
// Stuff for directed_graph and undirected_graph to skip over their first
// vertex_index and edge_index properties when providing vertex_all and
// edge_all; make sure you know the exact structure of your properties if you
// use there.
struct remove_first_property {
template <typename F>
struct result {
typedef typename boost::function_traits<F>::arg1_type a1;
typedef typename boost::remove_reference<a1>::type non_ref;
typedef typename non_ref::next_type nx;
typedef typename boost::mpl::if_<boost::is_const<non_ref>, boost::add_const<nx>, nx>::type with_const;
typedef typename boost::add_reference<with_const>::type type;
};
template <typename Prop>
typename Prop::next_type& operator()(Prop& p) const {return p.m_base;}
template <typename Prop>
const typename Prop::next_type& operator()(const Prop& p) const {return p.m_base;}
};
}
} // namesapce boost
#endif /* BOOST_PROPERTY_HPP */

View File

@@ -34,17 +34,23 @@ public:
}
static void get_graphs(const boost::property_tree::ptree& top,
size_t desired_idx /* or -1 for all */,
std::vector<const boost::property_tree::ptree*>& result) {
using boost::property_tree::ptree;
size_t current_idx = 0;
BOOST_FOREACH(const ptree::value_type& n, top) {
if (n.first == "graph") {
result.push_back(&n.second);
get_graphs(n.second, result);
if (current_idx == desired_idx || desired_idx == (size_t)(-1)) {
result.push_back(&n.second);
get_graphs(n.second, (size_t)(-1), result);
if (desired_idx != (size_t)(-1)) break;
}
++current_idx;
}
}
}
void run(std::istream& in)
void run(std::istream& in, size_t desired_idx)
{
using boost::property_tree::ptree;
ptree pt;
@@ -74,7 +80,7 @@ public:
}
// Search for graphs
std::vector<const ptree*> graphs;
get_graphs(gml, graphs);
get_graphs(gml, desired_idx, graphs);
BOOST_FOREACH(const ptree* gr, graphs) {
// Search for nodes
BOOST_FOREACH(const ptree::value_type& node, *gr) {
@@ -209,9 +215,9 @@ private:
namespace boost
{
void BOOST_GRAPH_DECL
read_graphml(std::istream& in, mutate_graph& g)
read_graphml(std::istream& in, mutate_graph& g, size_t desired_idx)
{
graphml_reader reader(g);
reader.run(in);
reader.run(in, desired_idx);
}
}

View File

@@ -124,6 +124,7 @@ test-suite graph_test :
[ run graphml_test.cpp ../build//boost_graph : : "graphml_test.xml" ]
[ run stoer_wagner_test.cpp ../../test/build//boost_unit_test_framework/<link>static : $(TEST_DIR) ]
[ compile filtered_graph_properties_dijkstra.cpp ]
[ run vf2_sub_graph_iso_test.cpp ]
;
# Run SDB tests only when -sSDB= is set.

View File

@@ -0,0 +1,293 @@
//=======================================================================
// Boost.Graph library vf2_sub_graph_iso test
// Adapted from isomorphism.cpp and mcgregor_subgraphs_test.cpp
//
// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com)
//
// 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 <iostream>
#include <fstream>
#include <map>
#include <algorithm>
#include <cstdlib>
#include <time.h>
#include <boost/test/minimal.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/vf2_sub_graph_iso.hpp>
#include <boost/graph/random.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/random.hpp>
#include <boost/random/variate_generator.hpp>
#include <boost/random/uniform_real.hpp>
#include <boost/random/uniform_int.hpp>
#include <boost/random/mersenne_twister.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/graph/graphviz.hpp>
using namespace boost;
template <typename Generator>
struct random_functor {
random_functor(Generator& g) : g(g) { }
std::size_t operator()(std::size_t n) {
boost::uniform_int<std::size_t> distrib(0, n-1);
boost::variate_generator<boost::mt19937&, boost::uniform_int<std::size_t> >
x(g, distrib);
return x();
}
Generator& g;
};
template<typename Graph1, typename Graph2>
void randomly_permute_graph(Graph1& g1, const Graph2& g2) {
BOOST_REQUIRE(num_vertices(g1) <= num_vertices(g2));
BOOST_REQUIRE(num_edges(g1) == 0);
typedef typename graph_traits<Graph1>::vertex_descriptor vertex1;
typedef typename graph_traits<Graph2>::vertex_descriptor vertex2;
typedef typename graph_traits<Graph1>::vertex_iterator vertex_iterator;
typedef typename graph_traits<Graph2>::edge_iterator edge_iterator;
boost::mt19937 gen;
random_functor<boost::mt19937> rand_fun(gen);
// Decide new order
std::vector<vertex2> orig_vertices;
std::copy(vertices(g2).first, vertices(g2).second, std::back_inserter(orig_vertices));
std::random_shuffle(orig_vertices.begin(), orig_vertices.end(), rand_fun);
std::map<vertex2, vertex1> vertex_map;
std::size_t i = 0;
for (vertex_iterator vi = vertices(g1).first;
vi != vertices(g1).second; ++i, ++vi) {
vertex_map[orig_vertices[i]] = *vi;
put(vertex_name_t(), g1, *vi, get(vertex_name_t(), g2, orig_vertices[i]));
}
for (edge_iterator ei = edges(g2).first; ei != edges(g2).second; ++ei) {
typename std::map<vertex2, vertex1>::iterator si = vertex_map.find(source(*ei, g2)),
ti = vertex_map.find(target(*ei, g2));
if ((si != vertex_map.end()) && (ti != vertex_map.end()))
add_edge(si->second, ti->second, get(edge_name_t(), g2, *ei), g1);
}
}
template<typename Graph>
void generate_random_digraph(Graph& g, double edge_probability,
int max_parallel_edges, double parallel_edge_probability,
int max_edge_name, int max_vertex_name) {
BOOST_REQUIRE((0 <= edge_probability) && (edge_probability <= 1));
BOOST_REQUIRE((0 <= parallel_edge_probability) && (parallel_edge_probability <= 1));
BOOST_REQUIRE(0 <= max_parallel_edges);
BOOST_REQUIRE(0 <= max_edge_name);
BOOST_REQUIRE(0 <= max_vertex_name);
typedef typename graph_traits<Graph>::vertex_iterator vertex_iterator;
boost::mt19937 random_gen;
boost::uniform_real<double> dist_real(0.0, 1.0);
boost::variate_generator<boost::mt19937&, boost::uniform_real<double> >
random_real_dist(random_gen, dist_real);
for (vertex_iterator u = vertices(g).first; u != vertices(g).second; ++u) {
for (vertex_iterator v = vertices(g).first; v != vertices(g).second; ++v) {
if (random_real_dist() <= edge_probability) {
add_edge(*u, *v, g);
for (int i = 0; i < max_parallel_edges; ++i) {
if (random_real_dist() <= parallel_edge_probability)
add_edge(*u, *v, g);
}
}
}
}
{
boost::uniform_int<int> dist_int(0, max_edge_name);
boost::variate_generator<boost::mt19937&, boost::uniform_int<int> >
random_int_dist(random_gen, dist_int);
randomize_property<vertex_name_t>(g, random_int_dist);
}
{
boost::uniform_int<int> dist_int(0, max_vertex_name);
boost::variate_generator<boost::mt19937&, boost::uniform_int<int> >
random_int_dist(random_gen, dist_int);
randomize_property<edge_name_t>(g, random_int_dist);
}
}
template <typename Graph1,
typename Graph2,
typename EdgeEquivalencePredicate,
typename VertexEquivalencePredicate>
struct test_callback {
test_callback(const Graph1& graph1, const Graph2& graph2,
EdgeEquivalencePredicate edge_comp,
VertexEquivalencePredicate vertex_comp, bool output)
: graph1_(graph1), graph2_(graph2), edge_comp_(edge_comp), vertex_comp_(vertex_comp),
output_(output) {}
template <typename CorrespondenceMap1To2,
typename CorrespondenceMap2To1>
bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) {
bool verified;
BOOST_CHECK(verified = verify_vf2_subgraph_iso(graph1_, graph2_, f, edge_comp_, vertex_comp_));
// Output (sub)graph isomorphism map
if (!verified || output_) {
std::cout << "Verfied: " << std::boolalpha << verified << std::endl;
std::cout << "Num vertices: " << num_vertices(graph1_) << ' ' << num_vertices(graph2_) << std::endl;
BGL_FORALL_VERTICES_T(v, graph1_, Graph1)
std::cout << '(' << get(vertex_index_t(), graph1_, v) << ", "
<< get(vertex_index_t(), graph2_, get(f, v)) << ") ";
std::cout << std::endl;
}
return true;
}
private:
const Graph1& graph1_;
const Graph2& graph2_;
EdgeEquivalencePredicate edge_comp_;
VertexEquivalencePredicate vertex_comp_;
bool output_;
};
void test_vf2_sub_graph_iso(int n1, int n2, double edge_probability,
int max_parallel_edges, double parallel_edge_probability,
int max_edge_name, int max_vertex_name, bool output) {
typedef property<edge_name_t, int> edge_property;
typedef property<vertex_name_t, int, property<vertex_index_t, int> > vertex_property;
typedef adjacency_list<listS, listS, bidirectionalS, vertex_property, edge_property> graph1;
typedef adjacency_list<vecS, vecS, bidirectionalS, vertex_property, edge_property> graph2;
graph1 g1(n1);
graph2 g2(n2);
generate_random_digraph(g2, edge_probability, max_parallel_edges, parallel_edge_probability,
max_edge_name, max_vertex_name);
randomly_permute_graph(g1, g2);
int v_idx = 0;
for (graph_traits<graph1>::vertex_iterator vi = vertices(g1).first;
vi != vertices(g1).second; ++vi) {
put(vertex_index_t(), g1, *vi, v_idx++);
}
// Create vertex and edge predicates
typedef property_map<graph1, vertex_name_t>::type vertex_name_map1;
typedef property_map<graph2, vertex_name_t>::type vertex_name_map2;
typedef property_map_equivalent<vertex_name_map1, vertex_name_map2> vertex_predicate;
vertex_predicate vertex_comp =
make_property_map_equivalent(get(vertex_name, g1), get(vertex_name, g2));
typedef property_map<graph1, edge_name_t>::type edge_name_map1;
typedef property_map<graph2, edge_name_t>::type edge_name_map2;
typedef property_map_equivalent<edge_name_map1, edge_name_map2> edge_predicate;
edge_predicate edge_comp =
make_property_map_equivalent(get(edge_name, g1), get(edge_name, g2));
std::clock_t start = std::clock();
// Create callback
test_callback<graph1, graph2, edge_predicate, vertex_predicate>
callback(g1, g2, edge_comp, vertex_comp, output);
std::cout << std::endl;
BOOST_CHECK(vf2_subgraph_iso(g1, g2, callback, vertex_order_by_mult(g1),
edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)));
std::clock_t end1 = std::clock();
std::cout << "vf2_subgraph_iso: elapsed time (clock cycles): " << (end1 - start) << std::endl;
if (num_vertices(g1) == num_vertices(g2)) {
std::cout << std::endl;
BOOST_CHECK(vf2_graph_iso(g1, g2, callback, vertex_order_by_mult(g1),
edges_equivalent(edge_comp).vertices_equivalent(vertex_comp)));
std::clock_t end2 = std::clock();
std::cout << "vf2_graph_iso: elapsed time (clock cycles): " << (end2 - end1) << std::endl;
}
if (output) {
std::fstream file_graph1("graph1.dot", std::fstream::out);
write_graphviz(file_graph1, g1,
make_label_writer(get(boost::vertex_name, g1)),
make_label_writer(get(boost::edge_name, g1)));
std::fstream file_graph2("graph2.dot", std::fstream::out);
write_graphviz(file_graph2, g2,
make_label_writer(get(boost::vertex_name, g2)),
make_label_writer(get(boost::edge_name, g2)));
}
}
int test_main(int argc, char* argv[]) {
int num_vertices_g1 = 10;
int num_vertices_g2 = 20;
double edge_probability = 0.4;
int max_parallel_edges = 2;
double parallel_edge_probability = 0.4;
int max_edge_name = 5;
int max_vertex_name = 5;
bool output = false;
if (argc > 1) {
num_vertices_g1 = boost::lexical_cast<int>(argv[1]);
}
if (argc > 2) {
num_vertices_g2 = boost::lexical_cast<int>(argv[2]);
}
if (argc > 3) {
edge_probability = boost::lexical_cast<double>(argv[3]);
}
if (argc > 4) {
max_parallel_edges = boost::lexical_cast<int>(argv[4]);
}
if (argc > 5) {
parallel_edge_probability = boost::lexical_cast<double>(argv[5]);
}
if (argc > 6) {
max_edge_name = boost::lexical_cast<int>(argv[6]);
}
if (argc > 7) {
max_vertex_name = boost::lexical_cast<int>(argv[7]);
}
if (argc > 8) {
output = boost::lexical_cast<bool>(argv[8]);
}
test_vf2_sub_graph_iso(num_vertices_g1, num_vertices_g2, edge_probability,
max_parallel_edges, parallel_edge_probability,
max_edge_name, max_vertex_name, output);
return 0;
}