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(); }