From 8431fde428d3baf44eeff7166cece23f5ead3904 Mon Sep 17 00:00:00 2001
From: Jeremiah Willcock
Date: Wed, 25 Nov 2009 21:56:36 +0000
Subject: [PATCH] Added lookup_edge() function as wrapper for graphs that do
not model AdjacencyMatrix; changed functions to use it instead of edge();
added is_adjacency_matrix traits class; updated docs to reflect Adjacency
Matrix requirements and suggestions; fixes #3266
[SVN r57928]
---
doc/kolmogorov_max_flow.html | 4 +-
doc/transitive_closure.html | 5 +-
.../boost/graph/bron_kerbosch_all_cliques.hpp | 10 ++--
.../boost/graph/clustering_coefficient.hpp | 7 +--
include/boost/graph/graph_traits.hpp | 10 ++++
include/boost/graph/kolmogorov_max_flow.hpp | 3 +-
include/boost/graph/lookup_edge.hpp | 48 +++++++++++++++++++
include/boost/graph/metric_tsp_approx.hpp | 3 +-
8 files changed, 76 insertions(+), 14 deletions(-)
create mode 100644 include/boost/graph/lookup_edge.hpp
diff --git a/doc/kolmogorov_max_flow.html b/doc/kolmogorov_max_flow.html
index f57a5762..2cafd055 100644
--- a/doc/kolmogorov_max_flow.html
+++ b/doc/kolmogorov_max_flow.html
@@ -216,7 +216,9 @@ of Kolmogorov. Few changes were made for increasing performance:
Vertex List Graph, Edge
List Graph and Incidence Graph.
For each edge (u,v) in the graph, the reverse edge (v,u)
-must also be in the graph.
+must also be in the graph. Performance of the algorithm will be slightly
+improved if the graph type also models Adjacency
+Matrix.
IN: vertex_descriptor src
diff --git a/doc/transitive_closure.html b/doc/transitive_closure.html
index e8793304..58c33182 100644
--- a/doc/transitive_closure.html
+++ b/doc/transitive_closure.html
@@ -56,8 +56,9 @@ Thanks to Vladimir Prus for the implementation of this algorithm!
IN: const Graph& g
A directed graph, where the Graph type must model the
- Vertex List Graph
- and Adjacency Graph concepts.
+ Vertex List Graph,
+ Adjacency Graph,
+ and Adjacency Matrix concepts.
Python: The parameter is named graph.
diff --git a/include/boost/graph/bron_kerbosch_all_cliques.hpp b/include/boost/graph/bron_kerbosch_all_cliques.hpp
index bf7e3ff4..f6d253b1 100644
--- a/include/boost/graph/bron_kerbosch_all_cliques.hpp
+++ b/include/boost/graph/bron_kerbosch_all_cliques.hpp
@@ -12,6 +12,7 @@
#include
#include
+#include
#include
namespace boost {
@@ -125,9 +126,7 @@ namespace detail
typename graph_traits::vertex_descriptor v,
typename graph_traits::undirected_category)
{
- function_requires< AdjacencyMatrixConcept >();
-
- return edge(u, v, g).second;
+ return lookup_edge(u, v, g).second;
}
template
@@ -137,13 +136,12 @@ namespace detail
typename graph_traits::vertex_descriptor v,
typename graph_traits::directed_category)
{
- function_requires< AdjacencyMatrixConcept >();
// Note that this could alternate between using an || to determine
// full connectivity. I believe that this should produce strongly
// connected components. Note that using && instead of || will
// change the results to a fully connected subgraph (i.e., symmetric
// edges between all vertices s.t., if a->b, then b->a.
- return edge(u, v, g).second && edge(v, u, g).second;
+ return lookup_edge(u, v, g).second && lookup_edge(v, u, g).second;
}
template
@@ -189,7 +187,7 @@ namespace detail
for(ni = nots.begin(); ni != nend; ++ni) {
for(ci = cands.begin(); ci != cend; ++ci) {
// if we don't find an edge, then we're okay.
- if(!edge(*ni, *ci, g).second) break;
+ if(!lookup_edge(*ni, *ci, g).second) break;
}
// if we iterated all the way to the end, then *ni
// is connected to all *ci
diff --git a/include/boost/graph/clustering_coefficient.hpp b/include/boost/graph/clustering_coefficient.hpp
index c84c4802..e5f94d9f 100644
--- a/include/boost/graph/clustering_coefficient.hpp
+++ b/include/boost/graph/clustering_coefficient.hpp
@@ -10,6 +10,7 @@
#include
#include
#include
+#include
namespace boost
{
@@ -42,8 +43,8 @@ namespace detail
{
function_requires< AdjacencyMatrixConcept >();
- return (edge(u, v, g).second ? 1 : 0) +
- (edge(v, u, g).second ? 1 : 0);
+ return (lookup_edge(u, v, g).second ? 1 : 0) +
+ (lookup_edge(v, u, g).second ? 1 : 0);
}
// This template matches undirectedS
@@ -55,7 +56,7 @@ namespace detail
undirected_tag)
{
function_requires< AdjacencyMatrixConcept >();
- return edge(u, v, g).second ? 1 : 0;
+ return lookup_edge(u, v, g).second ? 1 : 0;
}
}
diff --git a/include/boost/graph/graph_traits.hpp b/include/boost/graph/graph_traits.hpp
index b86ef0a8..89687b5d 100644
--- a/include/boost/graph/graph_traits.hpp
+++ b/include/boost/graph/graph_traits.hpp
@@ -181,6 +181,16 @@ namespace boost {
>::value
>
{ };
+
+ template
+ struct is_adjacency_matrix
+ : mpl::bool_<
+ is_convertible<
+ typename graph_traits::traversal_category,
+ adjacency_matrix_tag
+ >::value
+ >
+ { };
//@}
/** @name Directed Graph Traits
diff --git a/include/boost/graph/kolmogorov_max_flow.hpp b/include/boost/graph/kolmogorov_max_flow.hpp
index 328bd303..f98a5721 100644
--- a/include/boost/graph/kolmogorov_max_flow.hpp
+++ b/include/boost/graph/kolmogorov_max_flow.hpp
@@ -46,6 +46,7 @@
#include
#include
#include
+#include
namespace boost {
namespace detail {
@@ -161,7 +162,7 @@ namespace boost {
}
edge_descriptor to_sink;
bool is_there;
- tie(to_sink, is_there) = edge(current_node, m_sink, m_g);
+ tie(to_sink, is_there) = lookup_edge(current_node, m_sink, m_g);
if(is_there){
tEdgeVal cap_from_source = m_res_cap_map[from_source];
tEdgeVal cap_to_sink = m_res_cap_map[to_sink];
diff --git a/include/boost/graph/lookup_edge.hpp b/include/boost/graph/lookup_edge.hpp
new file mode 100644
index 00000000..72a2d9db
--- /dev/null
+++ b/include/boost/graph/lookup_edge.hpp
@@ -0,0 +1,48 @@
+//=======================================================================
+// Copyright 2009 Trustees of Indiana University
+// Author: Jeremiah Willcock
+//
+// Distributed under the Boost Software License, Version 1.0. (See
+// accompanying file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+//=======================================================================
+
+#ifndef BOOST_GRAPH_LOOKUP_EDGE_HPP
+#define BOOST_GRAPH_LOOKUP_EDGE_HPP
+
+#include
+#include
+#include
+#include
+
+// lookup_edge: a function that acts like edge() but falls back to out_edges()
+// and a search when edge() is not provided.
+
+namespace boost {
+
+ template
+ std::pair::edge_descriptor, bool>
+ lookup_edge(typename boost::graph_traits::vertex_descriptor src,
+ typename boost::graph_traits::vertex_descriptor tgt,
+ const Graph& g,
+ typename boost::enable_if, int>::type = 0) {
+ return edge(src, tgt, g);
+ }
+
+ template
+ std::pair::edge_descriptor, bool>
+ lookup_edge(typename boost::graph_traits::vertex_descriptor src,
+ typename boost::graph_traits::vertex_descriptor tgt,
+ const Graph& g,
+ typename boost::disable_if, int>::type = 0) {
+ typedef typename boost::graph_traits::out_edge_iterator it;
+ typedef typename boost::graph_traits::edge_descriptor edesc;
+ std::pair oe = out_edges(src, g);
+ for (; oe.first != oe.second; ++oe.first) {
+ edesc e = *oe.first;
+ if (target(e, g) == tgt) return std::make_pair(e, true);
+ }
+ return std::make_pair(edesc(), false);
+ }
+
+}
diff --git a/include/boost/graph/metric_tsp_approx.hpp b/include/boost/graph/metric_tsp_approx.hpp
index ef4c7ff5..7c18b8e0 100644
--- a/include/boost/graph/metric_tsp_approx.hpp
+++ b/include/boost/graph/metric_tsp_approx.hpp
@@ -34,6 +34,7 @@
#include
#include
#include
+#include
namespace boost
@@ -284,7 +285,7 @@ namespace boost
// would require revisiting the core algorithm.
Edge e;
bool found;
- tie(e, found) = edge(previous_, v, g);
+ tie(e, found) = lookup_edge(previous_, v, g);
if(!found) {
throw not_complete();
}