diff --git a/doc/distance_recorder.html b/doc/distance_recorder.html
index fe7cd559..a6b05fe2 100644
--- a/doc/distance_recorder.html
+++ b/doc/distance_recorder.html
@@ -153,7 +153,7 @@ A convenient way to create a distance_recorder.
Visitor concepts
The following are other event visitors: predecessor_recorder,
+ href="./predecessor_recorder.html">predecessor_recorder,
time_stamper,
and property_writer.
diff --git a/doc/edge_predecessor_recorder.html b/doc/edge_predecessor_recorder.html
new file mode 100644
index 00000000..9ed626b6
--- /dev/null
+++ b/doc/edge_predecessor_recorder.html
@@ -0,0 +1,197 @@
+
+
+
+Boost Graph Library: edge_predecessor_recorder
+
+
+
+
+
+
+
+edge_predecessor_recorder<PredEdgeMap, EventTag>
+
+
+
+This is an EventVisitor that records
+the predecessor (or parent) edge of a vertex in a property
+map. This is particularly useful in graph search algorithms where
+recording the predecessors is an efficient way to encode the search
+tree that was traversed during the search. The edge predecessor recorder is
+typically used with the on_tree_edge or
+on_relax_edge events and cannot be used with vertex events. This
+visitor is meant to be used instead of predecessor_recorder when a
+graph has parallel edges and it is necessary to know which incoming edge a
+search algorithm
+used to get to a particular vertex.
+
+
+edge_predecessor_recorder can be used with graph algorithms by
+wrapping it with an algorithm-specific adaptor, such as bfs_visitor and dfs_visitor. Also, this event
+visitor can be combined with other event visitors using
+std::pair to form an EventVisitorList.
+
+
+Algorithms such as Dijkstra's and breadth-first search will not assign
+a predecessor edge to the source vertex (which is the root of the search
+tree). It is often useful to initialize the source vertex's
+predecessor to a special value, thereby identifying the root vertex.
+When using an algorithm like
+depth-first search that creates a forest (multiple search trees) it
+is useful to do the same for every vertex. This
+way all the root nodes can be distinguished.
+
+
+
+
+
Model of
+
+EventVisitor
+
+
+Where Defined
+
+
+
+boost/graph/visitors.hpp
+
+
Template Parameters
+
+
+
+
+| Parameter | Description | Default |
+
+
+| PredEdgeMap |
+
+A WritablePropertyMap
+where the key and value types are the vertex and edge descriptor types, respectively, of the graph.
+ |
+ |
+
+
+| EventTag |
+
+The tag to specify when the edge_predecessor_recorder should be
+applied during the graph algorithm. EventTag must be an
+edge event.
+ |
+ |
+
+
+
+
+Associated Types
+
+
+
+
+| Type | Description |
+
+
+
+| edge_predecessor_recorder::event_filter |
+
+This will be the same type as the template parameter EventTag.
+ |
+
+
+
+
+Member Functions
+
+
+
+
+
+| Member | Description |
+
+
+
+|
+edge_predecessor_recorder(PredEdgeMap pa);
+ |
+
+Construct an edge predecessor recorder object with predecessor property map
+pa.
+ |
+
+
+
+
+template <class Edge, class Graph>
+void operator()(Edge e, const Graph& g);
+ |
+
+Given edge e = (u,v), this records e as the
+predecessor (or parent) edge of v.
+ |
+
+
+
+
+Non-Member Functions
+
+
+
+| Function | Description |
+
+
+
+template <class PredEdgeMap, class Tag>
+edge_predecessor_recorder<PredEdgeMap, Tag>
+record_edge_predecessors(PredEdgeMap pa, Tag);
+ |
+A convenient way to create a edge_predecessor_recorder.
+ |
+
+
+
+See Also
+
+Visitor concepts
+
+The following are other event visitors: distance_recorder,
+time_stamper,
+and property_writer.
+
+
+
+
+
+
+
+
+
+
+
diff --git a/doc/isomorphism-impl.w b/doc/isomorphism-impl.w
index ffff817e..e881a946 100644
--- a/doc/isomorphism-impl.w
+++ b/doc/isomorphism-impl.w
@@ -174,7 +174,7 @@ need to consider those vertices that have the same vertex invariant
number. The number of vertices in a graph with the same vertex
invariant number $i$ is called the \emph{invariant multiplicity} for
$i$. In this implementation, by default we use the out-degree of the
-vertex as the vertex invariant, though the user can also supply there
+vertex as the vertex invariant, though the user can also supply their
own invariant function. The ability of the invariant function to prune
the search space varies widely with the type of graph.
diff --git a/doc/predecessor_recorder.html b/doc/predecessor_recorder.html
index 75fe44a6..6f600eaf 100644
--- a/doc/predecessor_recorder.html
+++ b/doc/predecessor_recorder.html
@@ -31,7 +31,7 @@ typically used with the on_tree_edge or
predecessor_recorder can be used with graph algorithms by
-wrapping it with the algorithm specific adaptor, such as bfs_visitor and dfs_visitor. Also, this event
visitor can be combined with other event visitors using
@@ -44,7 +44,7 @@ tree). It is often useful to initialize the source vertex's
predecessor to itself, thereby identifying the root vertex as the only
vertex which is its own parent. When using an algorithm like
depth-first search that creates a forest (multiple search trees) it
-is useful to intialize the predecessor of every vertex to itself. This
+is useful to initialize the predecessor of every vertex to itself. This
way all the root nodes can be distinguished.
diff --git a/doc/prim_minimum_spanning_tree.html b/doc/prim_minimum_spanning_tree.html
index c42d1e7f..324f4196 100644
--- a/doc/prim_minimum_spanning_tree.html
+++ b/doc/prim_minimum_spanning_tree.html
@@ -67,6 +67,7 @@ PRIM-MST(G, s, w)
for each vertex u in V[G]
color[u] := WHITE
d[u] := infinity
+ end for
color[s] := GRAY
d[s] := 0
ENQUEUE(PQ, s)
diff --git a/doc/table_of_contents.html b/doc/table_of_contents.html
index db02575c..6032e9cc 100644
--- a/doc/table_of_contents.html
+++ b/doc/table_of_contents.html
@@ -90,6 +90,7 @@
Event Visitors
- predecessor_recorder
+
- edge_predecessor_recorder
- distance_recorder
- time_stamper
- property_writer
diff --git a/include/boost/graph/biconnected_components.hpp b/include/boost/graph/biconnected_components.hpp
index 418da06f..9586f9a2 100644
--- a/include/boost/graph/biconnected_components.hpp
+++ b/include/boost/graph/biconnected_components.hpp
@@ -36,19 +36,21 @@ namespace boost
(ComponentMap comp, std::size_t& c, DiscoverTimeMap dtm,
std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred,
OutputIterator out, Stack& S, DFSVisitor vis)
- : comp(comp), c(c), dtm(dtm), dfs_time(dfs_time), lowpt(lowpt),
+ : comp(comp), c(c), children_of_root(0), dtm(dtm),
+ dfs_time(dfs_time), lowpt(lowpt),
pred(pred), out(out), S(S), vis(vis) { }
template
void initialize_vertex(const Vertex& u, Graph& g)
{
+ put(pred, u, u);
vis.initialize_vertex(u, g);
}
template
void start_vertex(const Vertex& u, Graph& g)
{
- put(pred, u, u);
+ children_of_root = 0;
vis.start_vertex(u, g);
}
@@ -69,8 +71,14 @@ namespace boost
template
void tree_edge(const Edge& e, Graph& g)
{
+ typename boost::graph_traits::vertex_descriptor src = source(e, g);
+ typename boost::graph_traits::vertex_descriptor tgt = target(e, g);
+
S.push(e);
- put(pred, target(e, g), source(e, g));
+ put(pred, tgt, src);
+ if ( get(pred, src) == src ) {
+ ++children_of_root;
+ }
vis.tree_edge(e, g);
}
@@ -79,11 +87,14 @@ namespace boost
{
BOOST_USING_STD_MIN();
- if ( target(e, g) != get(pred, source(e, g)) ) {
+ typename boost::graph_traits::vertex_descriptor src = source(e, g);
+ typename boost::graph_traits::vertex_descriptor tgt = target(e, g);
+ if ( ( tgt != get(pred, src) || get(pred, src) == src ) &&
+ get(dtm, tgt) < get(dtm, src) ) {
S.push(e);
- put(lowpt, source(e, g),
- min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, source(e, g)),
- get(dtm, target(e, g))));
+ put(lowpt, src,
+ min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, src),
+ get(dtm, tgt)));
}
vis.back_edge(e, g);
}
@@ -99,49 +110,35 @@ namespace boost
{
BOOST_USING_STD_MIN();
Vertex parent = get(pred, u);
- const std::size_t dtm_of_dubious_parent = get(dtm, parent);
- bool is_art_point = false;
- if ( dtm_of_dubious_parent > get(dtm, u) ) {
- parent = get(pred, parent);
- is_art_point = true;
- put(pred, get(pred, u), u);
- put(pred, u, parent);
- }
-
- if ( parent == u ) { // at top
- if ( get(dtm, u) + 1 == dtm_of_dubious_parent )
- is_art_point = false;
- } else {
- put(lowpt, parent,
- min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent),
- get(lowpt, u)));
-
- if (get(lowpt, u) >= get(dtm, parent)) {
- if ( get(dtm, parent) > get(dtm, get(pred, parent)) ) {
- put(pred, u, get(pred, parent));
- put(pred, parent, u);
- }
-
- while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) {
- put(comp, S.top(), c);
- S.pop();
- }
- put(comp, S.top(), c);
- S.pop();
- ++c;
- if ( S.empty() ) {
- put(pred, u, parent);
- put(pred, parent, u);
- }
+ if (parent == u) { // Root of tree is special
+ if (children_of_root >= 2) {
+ *out++ = u;
}
+ return;
+ }
+ put(lowpt, parent,
+ min BOOST_PREVENT_MACRO_SUBSTITUTION(get(lowpt, parent),
+ get(lowpt, u)));
+ if ( get(lowpt, u) >= get(dtm, parent) ) {
+ if ( get(pred, parent) != parent ) {
+ *out++ = parent;
+ }
+ while ( get(dtm, source(S.top(), g)) >= get(dtm, u) ) {
+ put(comp, S.top(), c);
+ S.pop();
+ }
+ assert (source(S.top(), g) == parent);
+ assert (target(S.top(), g) == u);
+ put(comp, S.top(), c);
+ S.pop();
+ ++c;
}
- if ( is_art_point )
- *out++ = u;
vis.finish_vertex(u, g);
}
ComponentMap comp;
std::size_t& c;
+ std::size_t children_of_root;
DiscoverTimeMap dtm;
std::size_t& dfs_time;
LowPointMap lowpt;
diff --git a/include/boost/graph/chrobak_payne_drawing.hpp b/include/boost/graph/chrobak_payne_drawing.hpp
index 6060171f..ef6ae5c9 100644
--- a/include/boost/graph/chrobak_payne_drawing.hpp
+++ b/include/boost/graph/chrobak_payne_drawing.hpp
@@ -11,6 +11,7 @@
#include
#include
+#include
#include
#include //for next and prior
#include
diff --git a/include/boost/graph/copy.hpp b/include/boost/graph/copy.hpp
index 576f9259..0dc6c664 100644
--- a/include/boost/graph/copy.hpp
+++ b/include/boost/graph/copy.hpp
@@ -69,6 +69,33 @@ namespace boost {
}
};
+ // Add a reverse_graph_edge_descriptor wrapper if the Graph is a
+ // reverse_graph but the edge descriptor is from the original graph (this
+ // case comes from the fact that transpose_graph uses reverse_graph
+ // internally but doesn't expose the different edge descriptor type to the
+ // user).
+ template
+ struct add_reverse_edge_descriptor {
+ typedef Desc type;
+ static Desc convert(const Desc& d) {return d;}
+ };
+
+ template
+ struct add_reverse_edge_descriptor > {
+ typedef reverse_graph_edge_descriptor type;
+ static reverse_graph_edge_descriptor convert(const Desc& d) {
+ return reverse_graph_edge_descriptor(d);
+ }
+ };
+
+ template
+ struct add_reverse_edge_descriptor, boost::reverse_graph > {
+ typedef reverse_graph_edge_descriptor type;
+ static reverse_graph_edge_descriptor convert(const reverse_graph_edge_descriptor& d) {
+ return d;
+ }
+ };
+
// Default edge and vertex property copiers
template
@@ -79,7 +106,7 @@ namespace boost {
template
void operator()(const Edge1& e1, Edge2& e2) const {
- put(edge_all_map2, e2, get(edge_all_map1, e1));
+ put(edge_all_map2, e2, get(edge_all_map1, add_reverse_edge_descriptor::convert(e1)));
}
typename property_map::const_type edge_all_map1;
mutable typename property_map::type edge_all_map2;
diff --git a/include/boost/graph/detail/adjacency_list.hpp b/include/boost/graph/detail/adjacency_list.hpp
index 2ff293e1..100c44ba 100644
--- a/include/boost/graph/detail/adjacency_list.hpp
+++ b/include/boost/graph/detail/adjacency_list.hpp
@@ -2759,17 +2759,6 @@ namespace boost {
#if !defined(BOOST_NO_TEMPLATE_PARTIAL_SPECIALIZATION)
namespace boost {
- #if BOOST_WORKAROUND( _STLPORT_VERSION, >= 0x500 )
- // STLport 5 already defines a hash specialization.
- #else
- template <>
- struct hash< void* > // Need this when vertex_descriptor=void*
- {
- std::size_t
- operator()(void* v) const { return (std::size_t)v; }
- };
- #endif
-
template
struct hash< boost::detail::stored_edge >
{
diff --git a/include/boost/graph/directed_graph.hpp b/include/boost/graph/directed_graph.hpp
index 992546d4..0bf02519 100644
--- a/include/boost/graph/directed_graph.hpp
+++ b/include/boost/graph/directed_graph.hpp
@@ -410,7 +410,7 @@ template
typename DIRECTED_GRAPH::vertex_descriptor
vertex(typename DIRECTED_GRAPH::vertices_size_type n,
DIRECTED_GRAPH const& g)
-{ return vertex(g.impl()); }
+{ return vertex(n, g.impl()); }
template
std::pair
diff --git a/include/boost/graph/isomorphism.hpp b/include/boost/graph/isomorphism.hpp
index cc28e001..bbdd1f7b 100644
--- a/include/boost/graph/isomorphism.hpp
+++ b/include/boost/graph/isomorphism.hpp
@@ -154,7 +154,7 @@ namespace boost {
{
std::vector multiplicity(max_invariant, 0);
BGL_FORALL_VERTICES_T(v, G1, Graph1)
- ++multiplicity[invariant1(v)];
+ ++multiplicity.at(invariant1(v));
sort(V_mult, compare_multiplicity(invariant1, &multiplicity[0]));
}
@@ -303,7 +303,7 @@ namespace boost {
}
// The largest possible vertex invariant number
size_type max BOOST_PREVENT_MACRO_SUBSTITUTION () const {
- return (m_max_vertex_in_degree + 2) * m_max_vertex_out_degree + 1;
+ return (m_max_vertex_in_degree + 1) * (m_max_vertex_out_degree + 1);
}
private:
InDegreeMap m_in_degree_map;
diff --git a/include/boost/graph/kamada_kawai_spring_layout.hpp b/include/boost/graph/kamada_kawai_spring_layout.hpp
index f39ef90c..f8a210ca 100644
--- a/include/boost/graph/kamada_kawai_spring_layout.hpp
+++ b/include/boost/graph/kamada_kawai_spring_layout.hpp
@@ -218,7 +218,7 @@ namespace boost {
detail::graph::compute_edge_length(g, distance, index,
edge_or_side_length);
- std::cerr << "edge_length = " << edge_length << std::endl;
+ // std::cerr << "edge_length = " << edge_length << std::endl;
// Compute l_{ij} and k_{ij}
const weight_type K = spring_constant;
@@ -275,7 +275,7 @@ namespace boost {
E += .5 * k_ij * (dist - l_ij) * (dist - l_ij);
}
}
- std::cerr << "E = " << E << std::endl;
+ // std::cerr << "E = " << E << std::endl;
// Compute the elements of the Jacobian
// From
diff --git a/include/boost/graph/leda_graph.hpp b/include/boost/graph/leda_graph.hpp
index 687a10dd..af95692a 100644
--- a/include/boost/graph/leda_graph.hpp
+++ b/include/boost/graph/leda_graph.hpp
@@ -17,9 +17,9 @@
#include
#include
-#include
-#include
-#include
+#include
+#include
+#include
// The functions and classes in this file allows the user to
// treat a LEDA GRAPH object as a boost graph "as is". No
@@ -884,7 +884,7 @@ namespace boost {
inline
typename boost::property_traits<
typename boost::property_map,PropertyTag>::const_type
-::value_type
+ >::value_type
get(PropertyTag p, const leda::GRAPH& g, const Key& key) {
return get(get(p, g), key);
}
diff --git a/include/boost/graph/undirected_graph.hpp b/include/boost/graph/undirected_graph.hpp
index d5374101..3178b42a 100644
--- a/include/boost/graph/undirected_graph.hpp
+++ b/include/boost/graph/undirected_graph.hpp
@@ -413,7 +413,7 @@ template
typename UNDIRECTED_GRAPH::vertex_descriptor
vertex(typename UNDIRECTED_GRAPH::vertices_size_type n,
UNDIRECTED_GRAPH const& g)
-{ return vertex(g.impl()); }
+{ return vertex(n, g.impl()); }
template
std::pair
diff --git a/test/Jamfile.v2 b/test/Jamfile.v2
index e0cb54ac..8d26b17c 100644
--- a/test/Jamfile.v2
+++ b/test/Jamfile.v2
@@ -8,6 +8,7 @@
# LEDA (also top level directory) at the command line of jam using -s
import modules ;
+import path ;
path-constant TEST_DIR : . ;
@@ -124,23 +125,22 @@ test-suite graph_test :
;
# Run SDB tests only when -sSDB= is set.
-if [ modules.peek : SDB ] != ""
+local SDB = [ modules.peek : SDB ] ;
+if $(SDB)
{
- local SDB_DEPENDENCIES =
- $(SGB) $(SGB)/libgb.a ;
+ local sdb-root = [ path.root [ path.make $(SDB) ] [ path.pwd ] ] ;
- compile stanford_graph_cc.cpp
- $(SDB_DEPENDENCIES) ;
+ compile stanford_graph_cc.cpp :
+ $(sdb-root) ;
}
# Run LEDA tests only when -sLEDA= is set.
-if [ modules.peek : LEDA ] != ""
+local LEDA = [ modules.peek : LEDA ] ;
+if $(LEDA)
{
- local LEDA_DEPENDENCIES =
- $(LEDA)/incl
- $(LEDA)/libG.a
- ;
+ local leda-root = [ path.root [ path.make $(LEDA) ] [ path.pwd ] ] ;
+ local leda-include = [ path.join $(leda-root) incl ] ;
- compile leda_graph_cc.cpp
- $(LEDA_DEPENDENCIES) ;
+ compile leda_graph_cc.cpp :
+ $(leda-include) ;
}
diff --git a/test/biconnected_components_test.cpp b/test/biconnected_components_test.cpp
index ee37375f..6ec321a9 100644
--- a/test/biconnected_components_test.cpp
+++ b/test/biconnected_components_test.cpp
@@ -77,23 +77,11 @@ check_articulation_points(const Graph& g, std::vector art_points)
} else std::cout << "OK." << std::endl;
}
-int test_main(int argc, char* argv[])
-{
- std::size_t n = 100;
- std::size_t m = 500;
- std::size_t seed = 1;
+typedef adjacency_list Graph;
+typedef graph_traits::vertex_descriptor Vertex;
- if (argc > 1) n = lexical_cast(argv[1]);
- if (argc > 2) m = lexical_cast(argv[2]);
- if (argc > 3) seed = lexical_cast(argv[3]);
-
- typedef adjacency_list Graph;
- typedef graph_traits::vertex_descriptor Vertex;
-
- Graph g(n);
- minstd_rand gen(seed);
- generate_random_graph(g, n, m, gen);
+bool test_graph(Graph& g) { // Returns false on failure
std::vector art_points;
std::cout << "Computing biconnected components & articulation points... ";
@@ -127,5 +115,34 @@ int test_main(int argc, char* argv[])
out << "}\n";
}
+ return any_errors;
+}
+
+int test_main(int argc, char* argv[])
+{
+ std::size_t n = 100;
+ std::size_t m = 500;
+ std::size_t seed = 1;
+
+ if (argc > 1) n = lexical_cast(argv[1]);
+ if (argc > 2) m = lexical_cast(argv[2]);
+ if (argc > 3) seed = lexical_cast(argv[3]);
+
+ {
+ Graph g(n);
+ minstd_rand gen(seed);
+ generate_random_graph(g, n, m, gen);
+ if (test_graph(g)) return 1;
+ }
+
+ {
+ Graph g(4);
+ add_edge(2, 3, g);
+ add_edge(0, 3, g);
+ add_edge(0, 2, g);
+ add_edge(1, 0, g);
+ if (test_graph(g)) return 1;
+ }
+
return 0;
}