From d3d9fdc0e5f325d2a4e8db5d592b7cd92070edd5 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Tue, 8 Mar 2005 18:54:45 +0000 Subject: [PATCH] Lots of new algorithms and cleanups of old ones [SVN r27579] --- src/python/basic_graph.cpp | 7 + src/python/basic_graph.hpp | 24 ++- src/python/bellman_ford_events.hpp | 15 ++ src/python/bellman_ford_shortest_paths.cpp | 111 +++++++++++ src/python/betweenness_centrality.cpp | 175 +++++++++--------- src/python/biconnected_components.cpp | 1 + src/python/breadth_first_search.cpp | 57 +++++- src/python/circle_layout.cpp | 45 +++++ src/python/connected_components.cpp | 51 +++++ src/python/dag_shortest_paths.cpp | 103 +++++++++++ src/python/depth_first_search.cpp | 156 ++++++++++++++++ src/python/dfs_events.hpp | 18 ++ src/python/dijkstra_shortest_paths.cpp | 10 +- src/python/{done.hpp => dijkstra_visitor.hpp} | 19 +- src/python/done.cpp | 32 ---- src/python/fruchterman_reingold.cpp | 113 ++++++++++- src/python/incremental_components.cpp | 68 +++++++ src/python/isomorphism.cpp | 80 ++++++++ src/python/kamada_kawai_spring_layout.cpp | 80 ++++++++ src/python/kruskal_min_spanning_tree.cpp | 53 ++++++ src/python/module.cpp | 59 +++++- src/python/page_rank.cpp | 68 +++---- src/python/prim_minimum_spanning_tree.cpp | 105 +++++++++++ src/python/queue.hpp | 11 +- src/python/strong_components.cpp | 42 +++++ src/python/topological_sort.cpp | 55 ++++++ src/python/transitive_closure.cpp | 45 +++++ src/python/visitor.hpp | 13 +- 28 files changed, 1423 insertions(+), 193 deletions(-) create mode 100644 src/python/bellman_ford_events.hpp create mode 100644 src/python/bellman_ford_shortest_paths.cpp create mode 100644 src/python/circle_layout.cpp create mode 100644 src/python/connected_components.cpp create mode 100644 src/python/dag_shortest_paths.cpp create mode 100644 src/python/depth_first_search.cpp create mode 100644 src/python/dfs_events.hpp rename src/python/{done.hpp => dijkstra_visitor.hpp} (55%) delete mode 100644 src/python/done.cpp create mode 100644 src/python/incremental_components.cpp create mode 100644 src/python/isomorphism.cpp create mode 100644 src/python/kamada_kawai_spring_layout.cpp create mode 100644 src/python/kruskal_min_spanning_tree.cpp create mode 100644 src/python/prim_minimum_spanning_tree.cpp create mode 100644 src/python/strong_components.cpp create mode 100644 src/python/topological_sort.cpp create mode 100644 src/python/transitive_closure.cpp diff --git a/src/python/basic_graph.cpp b/src/python/basic_graph.cpp index bdb6b287..18dcec77 100644 --- a/src/python/basic_graph.cpp +++ b/src/python/basic_graph.cpp @@ -476,6 +476,13 @@ template void export_in_graph(); template void export_basic_graph(const char* name) { + using boost::python::class_; + using boost::python::init; + using boost::python::object; + using boost::python::range; + using boost::python::scope; + using boost::python::self; + typedef basic_graph Graph; typedef typename Graph::Vertex Vertex; typedef typename Graph::Edge Edge; diff --git a/src/python/basic_graph.hpp b/src/python/basic_graph.hpp index e41d4b4a..95160cbd 100644 --- a/src/python/basic_graph.hpp +++ b/src/python/basic_graph.hpp @@ -18,11 +18,12 @@ namespace boost { namespace graph { namespace python { -using namespace boost::python; - template bool type_already_registered() { - return objects::registered_class_object(python::type_id()).get() != 0; + using boost::python::objects::registered_class_object; + using boost::python::type_id; + + return registered_class_object(type_id()).get() != 0; } template @@ -34,15 +35,20 @@ public: typename std::iterator_traits::value_type next() { - if (first == last) objects::stop_iteration_error(); + using boost::python::objects::stop_iteration_error; + + if (first == last) stop_iteration_error(); return *first++; } static void declare(const char* name) { + using boost::python::class_; + using boost::python::no_init; + using boost::python::objects::identity_function; if (!type_already_registered()) class_ >(name, no_init) - .def("__iter__", objects::identity_function()) + .def("__iter__", identity_function()) .def("next", &simple_python_iterator::next) ; } @@ -63,6 +69,9 @@ struct declare_readable_property_map static void declare(const char* name) { + using boost::python::class_; + using boost::python::no_init; + if (!type_already_registered()) class_(name, no_init) .def("__getitem__", &getitem) @@ -85,6 +94,9 @@ struct declare_property_map static void declare(const char* name) { + using boost::python::class_; + using boost::python::no_init; + if (!type_already_registered()) class_(name, no_init) .def("__getitem__", &getitem) @@ -130,7 +142,6 @@ struct basic_index_map typedef typename property_traits::reference reference; typedef typename property_traits::category category; - basic_index_map() {} basic_index_map(const IndexMap& id = IndexMap()) : id(id) { } @@ -371,6 +382,7 @@ get(edge_index_t, const basic_graph& g) } } } // end namespace boost::graph::python #if 0 +// Triggers bugs in GCC namespace boost { template struct property_map, vertex_index_t> diff --git a/src/python/bellman_ford_events.hpp b/src/python/bellman_ford_events.hpp new file mode 100644 index 00000000..db31d60b --- /dev/null +++ b/src/python/bellman_ford_events.hpp @@ -0,0 +1,15 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +BGL_PYTHON_EVENT(initialize_vertex, vertex_descriptor) +BGL_PYTHON_EVENT(examine_edge, edge_descriptor) +BGL_PYTHON_EVENT(edge_relaxed, edge_descriptor) +BGL_PYTHON_EVENT(edge_not_relaxed, edge_descriptor) +BGL_PYTHON_EVENT(edge_minimized, edge_descriptor) +BGL_PYTHON_EVENT(edge_not_minimized, edge_descriptor) + diff --git a/src/python/bellman_ford_shortest_paths.cpp b/src/python/bellman_ford_shortest_paths.cpp new file mode 100644 index 00000000..22edacfc --- /dev/null +++ b/src/python/bellman_ford_shortest_paths.cpp @@ -0,0 +1,111 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include + +namespace boost { namespace graph { namespace python { + +#define BGL_PYTHON_VISITOR bellman_ford_visitor +#define BGL_PYTHON_EVENTS_HEADER "bellman_ford_events.hpp" +#include "visitor.hpp" +#undef BGL_PYTHON_EVENTS_HEADER +#undef BGL_PYTHON_VISITOR + +template +void +bellman_ford_shortest_paths + (Graph& g, typename Graph::Vertex s, + const vector_property_map* in_predecessor, + const vector_property_map* in_distance, + const vector_property_map* in_weight, + const bellman_ford_visitor& visitor) +{ + typedef vector_property_map + PredecessorMap; + typedef vector_property_map + DistanceMap; + typedef vector_property_map + WeightMap; + + PredecessorMap predecessor = + in_predecessor? *in_predecessor + : PredecessorMap(g.num_vertices(), g.get_vertex_index_map()); + + DistanceMap distance = + in_distance? *in_distance + : DistanceMap(g.num_vertices(), g.get_vertex_index_map()); + + WeightMap weight = in_weight? *in_weight + : g.template get_edge_map("weight"); + + typedef typename bellman_ford_visitor::default_arg default_visitor; + bool has_default_visitor = dynamic_cast(&visitor); + + if (!has_default_visitor) { + boost::bellman_ford_shortest_paths + (g, + root_vertex(s). + vertex_index_map(g.get_vertex_index_map()). + visitor(typename bellman_ford_visitor::ref(visitor)). + predecessor_map(predecessor). + distance_map(distance). + weight_map(weight)); + } else { + boost::bellman_ford_shortest_paths + (g, + root_vertex(s). + vertex_index_map(g.get_vertex_index_map()). + predecessor_map(predecessor). + distance_map(distance). + weight_map(weight)); + } +} + + +template +void export_bellman_ford_shortest_paths_in_graph() +{ + bellman_ford_visitor::declare("BellmanFordVisitor", + "DefaultBellmanFordVisitor"); +} + +void export_bellman_ford_shortest_paths() +{ + using boost::python::arg; + using boost::python::def; + + def("bellman_ford_shortest_paths", &bellman_ford_shortest_paths, + (arg("graph"), arg("root_vertex"), + arg("predecessor_map") = + (vector_property_map*)0, + arg("distance_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0, + arg("visitor") = bellman_ford_visitor::default_arg())); + + def("bellman_ford_shortest_paths", &bellman_ford_shortest_paths, + (arg("graph"), arg("root_vertex"), + arg("predecessor_map") = + (vector_property_map*)0, + arg("distance_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0, + arg("visitor") = bellman_ford_visitor::default_arg())); +} + +template void export_bellman_ford_shortest_paths_in_graph(); +template void export_bellman_ford_shortest_paths_in_graph(); + +} } } // end namespace boost::graph::python diff --git a/src/python/betweenness_centrality.cpp b/src/python/betweenness_centrality.cpp index d2d80032..8f821dd6 100644 --- a/src/python/betweenness_centrality.cpp +++ b/src/python/betweenness_centrality.cpp @@ -14,121 +14,120 @@ namespace boost { namespace graph { namespace python { template void -brandes_betweenness_centrality_ve +brandes_betweenness_centrality (Graph& g, - const vector_property_map& vertex_centrality, - const vector_property_map& edge_centrality) + const vector_property_map* in_vertex_centrality, + const vector_property_map* in_edge_centrality, + const vector_property_map* weight) { - brandes_betweenness_centrality - (g, - centrality_map(vertex_centrality). - edge_centrality_map(edge_centrality). - vertex_index_map(g.get_vertex_index_map())); -} + typedef vector_property_map + VertexCentralityMap; -template -inline void -brandes_betweenness_centrality_v - (Graph& g, - const vector_property_map& vertex_centrality) -{ - brandes_betweenness_centrality_ve(g, vertex_centrality, - g.template get_edge_map("centrality")); -} + typedef vector_property_map + EdgeCentralityMap; -template -void -brandes_betweenness_centrality_wve - (Graph& g, - const vector_property_map& weight, - const vector_property_map& vertex_centrality, - const vector_property_map& edge_centrality) -{ - brandes_betweenness_centrality - (g, - weight_map(weight). - centrality_map(vertex_centrality). - edge_centrality_map(edge_centrality). - vertex_index_map(g.get_vertex_index_map())); -} + VertexCentralityMap vertex_centrality = + in_vertex_centrality? *in_vertex_centrality + : g.template get_vertex_map("centrality"); -template -inline void -brandes_betweenness_centrality_wv - (Graph& g, - const vector_property_map& weight, - const vector_property_map& vertex_centrality) -{ - brandes_betweenness_centrality_wve(g, weight, vertex_centrality, - g.template get_edge_map("centrality")); -} + EdgeCentralityMap edge_centrality = + in_edge_centrality? *in_edge_centrality + : g.template get_edge_map("centrality"); -template -inline void -brandes_betweenness_centrality_w - (Graph& g, - const vector_property_map& weight) -{ - brandes_betweenness_centrality_wv(g, weight, - g.template get_vertex_map("centrality")); -} - -template -inline void -brandes_betweenness_centrality(Graph& g) -{ - brandes_betweenness_centrality_v(g, g.template get_vertex_map("centrality")); + if (weight) { + boost::brandes_betweenness_centrality + (g, + weight_map(*weight). + centrality_map(vertex_centrality). + edge_centrality_map(edge_centrality). + vertex_index_map(g.get_vertex_index_map())); + } else { + boost::brandes_betweenness_centrality + (g, + centrality_map(vertex_centrality). + edge_centrality_map(edge_centrality). + vertex_index_map(g.get_vertex_index_map())); + } } template void relative_betweenness_centrality (Graph& g, - const vector_property_map& centrality) -{ relative_betweenness_centrality(g, centrality); } + const vector_property_map* in_centrality) +{ + typedef vector_property_map + CentralityMap; + + CentralityMap centrality = + in_centrality? *in_centrality + : g.template get_vertex_map("centrality"); + + relative_betweenness_centrality(g, centrality); +} template double central_point_dominance (Graph& g, - const vector_property_map& centrality) -{ return boost::central_point_dominance(g, centrality); } + const vector_property_map* in_centrality) +{ + typedef vector_property_map + CentralityMap; + + CentralityMap centrality = + in_centrality? *in_centrality + : g.template get_vertex_map("centrality"); + + return boost::central_point_dominance(g, centrality); +} void export_betweenness_centrality() { + using boost::python::arg; + using boost::python::def; + // Graph def("brandes_betweenness_centrality", - &brandes_betweenness_centrality); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_v); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_ve); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_w); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_wv); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_wve); + &brandes_betweenness_centrality, + (arg("graph"), + arg("vertex_centrality_map") = + (vector_property_map*)0, + arg("edge_centrality_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0)); def("relative_betweenness_centrality", - &relative_betweenness_centrality); - def("central_point_dominance", ¢ral_point_dominance); + &relative_betweenness_centrality, + (arg("graph"), + arg("vertex_centrality_map") = + (vector_property_map*)0)); + def("central_point_dominance", + ¢ral_point_dominance, + (arg("graph"), + arg("vertex_centrality_map") = + (vector_property_map*)0)); // Digraph def("brandes_betweenness_centrality", - &brandes_betweenness_centrality); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_v); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_ve); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_w); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_wv); - def("brandes_betweenness_centrality", - &brandes_betweenness_centrality_wve); + &brandes_betweenness_centrality, + (arg("graph"), + arg("vertex_centrality_map") = + (vector_property_map*)0, + arg("edge_centrality_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0)); def("relative_betweenness_centrality", - &relative_betweenness_centrality); - def("central_point_dominance", ¢ral_point_dominance); + &relative_betweenness_centrality, + (arg("graph"), + arg("vertex_centrality_map") = + (vector_property_map*)0)); + def("central_point_dominance", + ¢ral_point_dominance, + (arg("graph"), + arg("vertex_centrality_map") = + (vector_property_map*)0)); } } } } // end namespace boost::graph::python diff --git a/src/python/biconnected_components.cpp b/src/python/biconnected_components.cpp index 222f7c3c..53d4f7bd 100644 --- a/src/python/biconnected_components.cpp +++ b/src/python/biconnected_components.cpp @@ -52,6 +52,7 @@ articulation_points(const Graph& g) void export_biconnected_components() { using boost::python::arg; + using boost::python::def; def("biconnected_components", &biconnected_components, (arg("graph"), diff --git a/src/python/breadth_first_search.cpp b/src/python/breadth_first_search.cpp index ebcc485d..43ca1cbc 100644 --- a/src/python/breadth_first_search.cpp +++ b/src/python/breadth_first_search.cpp @@ -21,7 +21,7 @@ namespace boost { namespace graph { namespace python { template void -breadth_first_search_qvs +breadth_first_search (const Graph& g, typename Graph::Vertex s, python_queue& Q, @@ -63,23 +63,74 @@ breadth_first_search_qvs } } +template +void +breadth_first_visit + (const Graph& g, + typename Graph::Vertex s, + python_queue& Q, + const bfs_visitor& visitor, + const vector_property_map& color) +{ + typedef typename python_queue::default_queue + default_queue_type; + + bool has_default_buffer = dynamic_cast(&Q); + bool has_default_visitor = + dynamic_cast::default_arg const*>(&visitor); + + if (has_default_buffer) { + if (has_default_visitor) { + boost::breadth_first_visit(g, s, color_map(color)); + } else { + boost::breadth_first_visit + (g, s, + color_map(color). + visitor(typename bfs_visitor::ref(visitor))); + } + } else { + if (has_default_visitor) { + boost::breadth_first_visit(g, s, + buffer(Q). + color_map(color)); + } else { + boost::breadth_first_visit + (g, s, Q, typename bfs_visitor::ref(visitor), color); + } + } +} + void export_breadth_first_search() { using boost::python::arg; + using boost::python::def; - def("breadth_first_search", &breadth_first_search_qvs, + def("breadth_first_search", &breadth_first_search, (arg("graph"), "root_vertex", arg("buffer") = python_queue::default_queue(), arg("visitor") = bfs_visitor::default_arg(), arg("color_map") = (vector_property_map*)0)); - def("breadth_first_search", &breadth_first_search_qvs, + def("breadth_first_visit", &breadth_first_visit, + (arg("graph"), "root_vertex", + arg("buffer") = python_queue::default_queue(), + arg("visitor") = bfs_visitor::default_arg(), + arg("color_map"))); + + def("breadth_first_search", &breadth_first_search, (arg("graph"), "root_vertex", arg("buffer") = python_queue::default_queue(), arg("visitor") = bfs_visitor::default_arg(), arg("color_map") = (vector_property_map*)0)); + + def("breadth_first_visit", &breadth_first_visit, + (arg("graph"), "root_vertex", + arg("buffer") = python_queue::default_queue(), + arg("visitor") = bfs_visitor::default_arg(), + arg("color_map"))); } template diff --git a/src/python/circle_layout.cpp b/src/python/circle_layout.cpp new file mode 100644 index 00000000..bc8ee2a3 --- /dev/null +++ b/src/python/circle_layout.cpp @@ -0,0 +1,45 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include "point2d.hpp" + +namespace boost { namespace graph { namespace python { + +template +void +circle_graph_layout + (Graph& g, + const vector_property_map* in_pos, + double radius) +{ + typedef vector_property_map + PositionMap; + + PositionMap pos = + in_pos? *in_pos : g.template get_vertex_map("position"); + + circle_graph_layout(g, pos, radius); +} + +void export_circle_graph_layout() +{ + using boost::python::arg; + using boost::python::def; + + def("circle_graph_layout", + &circle_graph_layout, + (arg("graph"), + arg("position") = + (vector_property_map*)0, + arg("radius") = 250.0)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/connected_components.cpp b/src/python/connected_components.cpp new file mode 100644 index 00000000..e91ffa56 --- /dev/null +++ b/src/python/connected_components.cpp @@ -0,0 +1,51 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include + +namespace boost { namespace graph { namespace python { + +template +int +connected_components + (Graph& g, + const vector_property_map* in_component, + const vector_property_map* in_color) +{ + typedef vector_property_map ComponentMap; + + typedef vector_property_map ColorMap; + + ComponentMap component = + in_component? *in_component : g.template get_vertex_map("component"); + + ColorMap color = + in_color? *in_color : ColorMap(g.num_vertices(), g.get_vertex_index_map()); + + return boost::connected_components(g, component, color_map(color)); +} + +void export_connected_components() +{ + using boost::python::arg; + using boost::python::def; + + def("connected_components", &connected_components, + (arg("graph"), + arg("component_map") = + (vector_property_map*)0, + arg("color_map") = + (vector_property_map*)0)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/dag_shortest_paths.cpp b/src/python/dag_shortest_paths.cpp new file mode 100644 index 00000000..88659bd5 --- /dev/null +++ b/src/python/dag_shortest_paths.cpp @@ -0,0 +1,103 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include +#include "dijkstra_visitor.hpp" + +namespace boost { namespace graph { namespace python { + +template +void +dag_shortest_paths + (Graph& g, typename Graph::Vertex s, + const vector_property_map* in_predecessor, + const vector_property_map* in_distance, + const vector_property_map* in_weight, + const dijkstra_visitor& visitor) +{ + typedef vector_property_map + PredecessorMap; + typedef vector_property_map + DistanceMap; + typedef vector_property_map + WeightMap; + + PredecessorMap predecessor = + in_predecessor? *in_predecessor + : PredecessorMap(g.num_vertices(), g.get_vertex_index_map()); + + DistanceMap distance = + in_distance? *in_distance + : DistanceMap(g.num_vertices(), g.get_vertex_index_map()); + + WeightMap weight = in_weight? *in_weight + : g.template get_edge_map("weight"); + + typedef typename dijkstra_visitor::default_arg default_visitor; + bool has_default_visitor = dynamic_cast(&visitor); + + if (!has_default_visitor) { + boost::dag_shortest_paths + (g, s, + vertex_index_map(g.get_vertex_index_map()). + visitor(typename dijkstra_visitor::ref(visitor)). + predecessor_map(predecessor). + distance_map(distance). + weight_map(weight)); + } else { + boost::dag_shortest_paths + (g, s, + vertex_index_map(g.get_vertex_index_map()). + predecessor_map(predecessor). + distance_map(distance). + weight_map(weight)); + } +} + +template +void export_dag_shortest_paths_in_graph() +{ + dijkstra_visitor::declare("DijkstraVisitor", + "DefaultDijkstraVisitor"); +} + +void export_dag_shortest_paths() +{ + using boost::python::arg; + using boost::python::def; + + def("dag_shortest_paths", &dag_shortest_paths, + (arg("graph"), arg("root_vertex"), + arg("predecessor_map") = + (vector_property_map*)0, + arg("distance_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0, + arg("visitor") = dijkstra_visitor::default_arg())); + + def("dag_shortest_paths", &dag_shortest_paths, + (arg("graph"), arg("root_vertex"), + arg("predecessor_map") = + (vector_property_map*)0, + arg("distance_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0, + arg("visitor") = dijkstra_visitor::default_arg())); +} + +template void export_dag_shortest_paths_in_graph(); +template void export_dag_shortest_paths_in_graph(); + +} } } // end namespace boost::graph::python diff --git a/src/python/depth_first_search.cpp b/src/python/depth_first_search.cpp new file mode 100644 index 00000000..ae3b7a5f --- /dev/null +++ b/src/python/depth_first_search.cpp @@ -0,0 +1,156 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include +#include "graph.hpp" +#include "digraph.hpp" +#include "queue.hpp" + +namespace boost { namespace graph { namespace python { + +#define BGL_PYTHON_VISITOR dfs_visitor +#define BGL_PYTHON_EVENTS_HEADER "dfs_events.hpp" +#include "visitor.hpp" +#undef BGL_PYTHON_EVENTS_HEADER +#undef BGL_PYTHON_VISITOR + +template +void +depth_first_search + (const Graph& g, + const dfs_visitor& visitor, + const vector_property_map* in_color) +{ + typedef vector_property_map ColorMap; + + ColorMap color = + in_color? *in_color : ColorMap(g.num_vertices(), g.get_vertex_index_map()); + + bool has_default_visitor = + dynamic_cast::default_arg const*>(&visitor); + + if (has_default_visitor) { + boost::depth_first_search(g, boost::dfs_visitor<>(), color); + } else { + boost::depth_first_search(g, typename dfs_visitor::ref(visitor), + color); + } +} + +template +void +depth_first_visit + (const Graph& g, + typename Graph::Vertex s, + const dfs_visitor& visitor, + const vector_property_map* in_color) +{ + typedef vector_property_map ColorMap; + + ColorMap color = + in_color? *in_color : ColorMap(g.num_vertices(), g.get_vertex_index_map()); + + bool has_default_visitor = + dynamic_cast::default_arg const*>(&visitor); + + if (has_default_visitor) { + boost::depth_first_visit(g, s, boost::dfs_visitor<>(), color); + } else { + boost::depth_first_visit(g, s, typename dfs_visitor::ref(visitor), + color); + } +} + +template +void +undirected_dfs + (const Graph& g, + const dfs_visitor& visitor, + const vector_property_map* in_color, + const vector_property_map* in_edge_color) +{ + typedef vector_property_map ColorMap; + typedef vector_property_map EdgeColorMap; + + ColorMap color = + in_color? *in_color : ColorMap(g.num_vertices(), g.get_vertex_index_map()); + + EdgeColorMap edge_color = + in_edge_color? *in_edge_color + : EdgeColorMap(g.num_edges(), g.get_edge_index_map()); + + bool has_default_visitor = + dynamic_cast::default_arg const*>(&visitor); + + if (has_default_visitor) { + boost::undirected_dfs(g, boost::dfs_visitor<>(), color, edge_color); + } else { + boost::undirected_dfs(g, typename dfs_visitor::ref(visitor), + color, edge_color); + } +} + +void export_depth_first_search() +{ + using boost::python::arg; + using boost::python::def; + + def("depth_first_search", &depth_first_search, + (arg("graph"), + arg("visitor") = dfs_visitor::default_arg(), + arg("color_map") = + (vector_property_map*)0)); + + def("depth_first_visit", &depth_first_visit, + (arg("graph"), + arg("root_vertex"), + arg("visitor") = dfs_visitor::default_arg(), + arg("color_map") = + (vector_property_map*)0)); + + def("undirected_dfs", &undirected_dfs, + (arg("graph"), + arg("visitor") = dfs_visitor::default_arg(), + arg("color_map") = + (vector_property_map*)0, + arg("edge_color_map") = + (vector_property_map*)0)); + + def("depth_first_search", &depth_first_search, + (arg("graph"), + arg("visitor") = dfs_visitor::default_arg(), + arg("color_map") = + (vector_property_map*)0)); + + def("depth_first_visit", &depth_first_visit, + (arg("graph"), + arg("root_vertex"), + arg("visitor") = dfs_visitor::default_arg(), + arg("color_map") = + (vector_property_map*)0)); +} + +template +void export_depth_first_search_in_graph() +{ + dfs_visitor::declare("DFSVisitor", "DefaultDFSVisitor"); +} + +template void export_depth_first_search_in_graph(); +template void export_depth_first_search_in_graph(); + +} } } // end namespace boost::graph::python diff --git a/src/python/dfs_events.hpp b/src/python/dfs_events.hpp new file mode 100644 index 00000000..d0813388 --- /dev/null +++ b/src/python/dfs_events.hpp @@ -0,0 +1,18 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +BGL_PYTHON_EVENT(initialize_vertex, vertex_descriptor) +BGL_PYTHON_EVENT(start_vertex, vertex_descriptor) +BGL_PYTHON_EVENT(discover_vertex, vertex_descriptor) +BGL_PYTHON_EVENT(examine_vertex, vertex_descriptor) +BGL_PYTHON_EVENT(examine_edge, edge_descriptor) +BGL_PYTHON_EVENT(tree_edge, edge_descriptor) +BGL_PYTHON_EVENT(back_edge, edge_descriptor) +BGL_PYTHON_EVENT(forward_or_cross_edge, edge_descriptor) +BGL_PYTHON_EVENT(finish_vertex, vertex_descriptor) diff --git a/src/python/dijkstra_shortest_paths.cpp b/src/python/dijkstra_shortest_paths.cpp index 9dc785e4..ff7db509 100644 --- a/src/python/dijkstra_shortest_paths.cpp +++ b/src/python/dijkstra_shortest_paths.cpp @@ -10,15 +10,10 @@ #include "graph.hpp" #include "digraph.hpp" #include +#include "dijkstra_visitor.hpp" namespace boost { namespace graph { namespace python { -#define BGL_PYTHON_VISITOR dijkstra_visitor -#define BGL_PYTHON_EVENTS_HEADER "dijkstra_events.hpp" -#include "visitor.hpp" -#undef BGL_PYTHON_EVENTS_HEADER -#undef BGL_PYTHON_VISITOR - template void dijkstra_shortest_paths @@ -69,7 +64,6 @@ dijkstra_shortest_paths } } - template void export_dijkstra_shortest_paths_in_graph() { @@ -80,7 +74,7 @@ void export_dijkstra_shortest_paths_in_graph() void export_dijkstra_shortest_paths() { using boost::python::arg; - + using boost::python::def; def("dijkstra_shortest_paths", &dijkstra_shortest_paths, (arg("graph"), arg("root_vertex"), diff --git a/src/python/done.hpp b/src/python/dijkstra_visitor.hpp similarity index 55% rename from src/python/done.hpp rename to src/python/dijkstra_visitor.hpp index f4218d30..520f2dc8 100644 --- a/src/python/done.hpp +++ b/src/python/dijkstra_visitor.hpp @@ -6,18 +6,15 @@ // Authors: Douglas Gregor // Andrew Lumsdaine -#ifndef BOOST_GRAPH_PYTHON_DONE_HPP -#define BOOST_GRAPH_PYTHON_DONE_HPP - +#ifndef BOOST_GRAPH_PYTHON_DIJKSTRA_VISITOR_HPP +#define BOOST_GRAPH_PYTHON_DIJKSTRA_VISITOR_HPP namespace boost { namespace graph { namespace python { -class done -{ - public: - virtual ~done() { } - virtual bool operator()() const = 0; -}; +#define BGL_PYTHON_VISITOR dijkstra_visitor +#define BGL_PYTHON_EVENTS_HEADER "dijkstra_events.hpp" +#include "visitor.hpp" +#undef BGL_PYTHON_EVENTS_HEADER +#undef BGL_PYTHON_VISITOR } } } // end namespace boost::graph::python - -#endif // BOOST_GRAPH_PYTHON_DONE_HPP +#endif BOOST_GRAPH_PYTHON_DIJKSTRA_VISITOR_HPP diff --git a/src/python/done.cpp b/src/python/done.cpp deleted file mode 100644 index fd350e20..00000000 --- a/src/python/done.cpp +++ /dev/null @@ -1,32 +0,0 @@ -// Copyright 2005 The Trustees of Indiana University. - -// Use, modification and distribution is subject to the Boost Software -// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at -// http://www.boost.org/LICENSE_1_0.txt) - -// Authors: Douglas Gregor -// Andrew Lumsdaine -#include "done.hpp" -#include - -namespace boost { namespace graph { namespace python { - -using namespace boost::python; - -class done_wrap : public done, public wrapper -{ -public: - bool operator()() const - { - return this->get_override("__call__")(); - } -}; - -void export_done() -{ - class_("Done") - .def("__call__", pure_virtual(&done::operator())) - ; -} - -} } } // end namespace boost::graph::python diff --git a/src/python/fruchterman_reingold.cpp b/src/python/fruchterman_reingold.cpp index e148cfda..6ae168a9 100644 --- a/src/python/fruchterman_reingold.cpp +++ b/src/python/fruchterman_reingold.cpp @@ -7,19 +7,130 @@ // Authors: Douglas Gregor // Andrew Lumsdaine #include +#include #include "graph.hpp" #include "digraph.hpp" +#include "point2d.hpp" +#include +#include namespace boost { namespace graph { namespace python { +template +struct python_or_functor +{ + explicit python_or_functor(boost::python::object callable, const F& f = F()) + : callable(callable), f(f) { } + + // For cooling + Result operator()() + { + using boost::python::object; + using boost::python::extract; + if (callable != object()) return extract(callable()); + else return f(); + } + + // For the attractive_force + template + Result + operator()(typename graph_traits::edge_descriptor e, + double k, double dist, const Graph& g) const + { + using boost::python::object; + using boost::python::extract; + if (callable != object()) return extract(callable(e, k, dist, g)); + else return f(e, k, dist, g); + } + + // For the repulsive_force + template + Result + operator()(typename graph_traits::vertex_descriptor u, + typename graph_traits::vertex_descriptor v, + double k, double dist, const Graph& g) const + { + using boost::python::object; + using boost::python::extract; + if (callable != object()) + return extract(callable(u, v, k, dist, g)); + else return f(u, v, k, dist, g); + } + +private: + boost::python::object callable; + F f; +}; + + template void fruchterman_reingold_force_directed_layout (Graph& g, const vector_property_map* in_pos, double width, double height, - ) + boost::python::object attractive_force, + boost::python::object repulsive_force, + // TBD: force pairs? + boost::python::object cooling, + bool progressive) { + using boost::python::object; + + typedef vector_property_map + PositionMap; + + PositionMap pos = + in_pos? *in_pos : g.template get_vertex_map("position"); + + if (!progressive) { + minstd_rand gen(std::time(0)); + random_graph_layout(g, pos, -width/2, width/2, -height/2, height/2, gen); + } + + python_or_functor > cool(cooling, 100); + + if (attractive_force != object() || repulsive_force != object()) { + python_or_functor fa(attractive_force); + python_or_functor fr(repulsive_force); + + boost::fruchterman_reingold_force_directed_layout + (g, pos, width, height, + boost::vertex_index_map(g.get_vertex_index_map()). + attractive_force(fa).repulsive_force(fr). + cooling(cool)); + } else { + if (cooling != object()) { + boost::fruchterman_reingold_force_directed_layout + (g, pos, width, height, + boost::vertex_index_map(g.get_vertex_index_map()). + cooling(cool)); + } else { + boost::fruchterman_reingold_force_directed_layout + (g, pos, width, height, + vertex_index_map(g.get_vertex_index_map())); + } + } +} + +void export_fruchterman_reingold_force_directed_layout() +{ + using boost::python::arg; + using boost::python::def; + using boost::python::object; + + def("fruchterman_reingold_force_directed_layout", + &fruchterman_reingold_force_directed_layout, + (arg("graph"), + arg("position") = + (vector_property_map*)0, + arg("width") = 500.0, + arg("height") = 500.0, + arg("attractive_force") = object(), + arg("repulsive_force") = object(), + arg("cooling") = object(), + arg("progressive") = false)); + } } } } // end namespace boost::graph::python diff --git a/src/python/incremental_components.cpp b/src/python/incremental_components.cpp new file mode 100644 index 00000000..100515c2 --- /dev/null +++ b/src/python/incremental_components.cpp @@ -0,0 +1,68 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include + +namespace boost { namespace graph { namespace python { + +template +class IncrementalComponents +{ +public: + typedef typename graph_traits::vertex_descriptor vertex_descriptor; + typedef vector_property_map ParentMap; + typedef vector_property_map RankMap; + + IncrementalComponents(const Graph& g) + : ds(RankMap(num_vertices(g), g.get_vertex_index_map()), + ParentMap(num_vertices(g), g.get_vertex_index_map())) + { + initialize_incremental_components(g, ds); + incremental_components(g, ds); + } + + void make_set(vertex_descriptor u) { ds.make_set(u); } + + void union_set(vertex_descriptor u, vertex_descriptor v) + { ds.union_set(u, v); } + + bool same_component(vertex_descriptor u, vertex_descriptor v) + { return boost::same_component(u, v, ds); } + +private: + disjoint_sets ds; +}; + +template +std::auto_ptr > +incremental_components(Graph& g) +{ + typedef std::auto_ptr > result_type; + return result_type(new IncrementalComponents(g)); +} + +void export_incremental_components() +{ + using boost::python::arg; + using boost::python::def; + using boost::python::class_; + using boost::python::no_init; + class_ >("IncrementalComponents", no_init) + .def("make_set", &IncrementalComponents::make_set) + .def("union_set", &IncrementalComponents::union_set) + .def("same_component", &IncrementalComponents::same_component) + ; + def("incremental_components", &incremental_components); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/isomorphism.cpp b/src/python/isomorphism.cpp new file mode 100644 index 00000000..73a995ee --- /dev/null +++ b/src/python/isomorphism.cpp @@ -0,0 +1,80 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include + +namespace boost { namespace graph { namespace python { + +template +struct py_vertex_invariant +{ + explicit py_vertex_invariant(boost::python::object invariant) + : invariant(invariant) { } + + int operator()(const Vertex& v1, const Vertex& v2) + { return boost::python::extract(invariant(v1, v2)); } + +private: + boost::python::object invariant; +}; + +template +bool +isomorphism + (Graph& g1, + Graph& g2, + const vector_property_map* in_iso, + boost::python::object invariant) +{ + typedef typename Graph::Vertex Vertex; + + typedef vector_property_map IsoMap; + + IsoMap iso = + in_iso? *in_iso + : IsoMap(num_vertices(g1), g1.get_vertex_index_map()); + + if (invariant != boost::python::object()) + return boost::isomorphism + (g1, g2, + isomorphism_map(iso). + vertex_invariant(py_vertex_invariant(invariant)). + vertex_index1_map(g1.get_vertex_index_map()). + vertex_index2_map(g2.get_vertex_index_map())); + else + return boost::isomorphism + (g1, g2, + isomorphism_map(iso). + vertex_index1_map(g1.get_vertex_index_map()). + vertex_index2_map(g2.get_vertex_index_map())); +} + +void export_isomorphism() +{ + using boost::python::arg; + using boost::python::def; + using boost::python::object; + + def("isomorphism", &isomorphism, + (arg("graph"), + arg("isomorphism_map") = + (vector_property_map*)0, + arg("vertex_invariant") = object())); + + def("isomorphism", &isomorphism, + (arg("graph"), + arg("isomorphism_map") = + (vector_property_map*)0, + arg("vertex_invariant") = object())); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/kamada_kawai_spring_layout.cpp b/src/python/kamada_kawai_spring_layout.cpp new file mode 100644 index 00000000..374815d6 --- /dev/null +++ b/src/python/kamada_kawai_spring_layout.cpp @@ -0,0 +1,80 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include +#include "graph.hpp" +#include "digraph.hpp" +#include "point2d.hpp" +#include + +namespace boost { namespace graph { namespace python { + +template +void +kamada_kawai_spring_layout + (Graph& g, + const vector_property_map* in_pos, + const vector_property_map* in_weight, + double side_length, + boost::python::object done, + double spring_constant, + bool progressive) +{ + using boost::python::object; + + typedef vector_property_map + PositionMap; + typedef vector_property_map + WeightMap; + + PositionMap pos = + in_pos? *in_pos : g.template get_vertex_map("position"); + + WeightMap weight = + in_weight? *in_weight : WeightMap(num_edges(g), g.get_edge_index_map()); + + // If we weren't give a weight map, assume unweighted edges + if (!in_weight) BGL_FORALL_EDGES_T(e, g, Graph) put(weight, e, 1.0); + + if (!progressive) circle_graph_layout(g, pos, side_length/2); + + if (done != object()) { + boost::kamada_kawai_spring_layout(g, pos, weight, + boost::side_length(side_length), done, + spring_constant, + g.get_vertex_index_map()); + } else { + boost::kamada_kawai_spring_layout(g, pos, weight, + boost::side_length(side_length), + layout_tolerance(), + spring_constant, + g.get_vertex_index_map()); + } +} + +void export_kamada_kawai_spring_layout() +{ + using boost::python::arg; + using boost::python::def; + using boost::python::object; + + def("kamada_kawai_spring_layout", + &kamada_kawai_spring_layout, + (arg("graph"), + arg("position") = + (vector_property_map*)0, + arg("weight") = + (vector_property_map*)0, + arg("side_length") = 500.0, + arg("done") = object(), + arg("spring_constant") = 1.0, + arg("progressive") = false)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/kruskal_min_spanning_tree.cpp b/src/python/kruskal_min_spanning_tree.cpp new file mode 100644 index 00000000..11bf0e2a --- /dev/null +++ b/src/python/kruskal_min_spanning_tree.cpp @@ -0,0 +1,53 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include +#include +#include + +namespace boost { namespace graph { namespace python { + +template +boost::python::list +kruskal_minimum_spanning_tree + (Graph& g, + const vector_property_map* in_weight) +{ + typedef vector_property_map WeightMap; + + WeightMap weight = + in_weight? *in_weight : g.template get_edge_map("weight"); + + std::list mst_edges; + boost::kruskal_minimum_spanning_tree + (g, + std::back_inserter(mst_edges), + vertex_index_map(g.get_vertex_index_map()). + weight_map(weight)); + boost::python::list result; + for (typename std::list::iterator i + = mst_edges.begin(); i != mst_edges.end(); ++i) + result.append(*i); + return result; +} + +void export_kruskal_minimum_spanning_tree() +{ + using boost::python::arg; + using boost::python::def; + + def("kruskal_minimum_spanning_tree", &kruskal_minimum_spanning_tree, + (arg("graph"), + arg("weight_map") = + (vector_property_map*)0)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/module.cpp b/src/python/module.cpp index 55066120..b585aa86 100644 --- a/src/python/module.cpp +++ b/src/python/module.cpp @@ -10,7 +10,7 @@ #include "graph.hpp" #include "digraph.hpp" #include -// #include "point2d.hpp" +#include "point2d.hpp" namespace boost { namespace graph { namespace python { @@ -18,22 +18,47 @@ extern void export_Graph(); extern void export_Digraph(); extern void export_betweenness_centrality(); extern void export_page_rank(); -extern void export_done(); extern void export_breadth_first_search(); +extern void export_depth_first_search(); extern void export_dijkstra_shortest_paths(); +extern void export_bellman_ford_shortest_paths(); +extern void export_dag_shortest_paths(); +extern void export_prim_minimum_spanning_tree(); template void export_breadth_first_search_in_graph(); +template void export_depth_first_search_in_graph(); template void export_dijkstra_shortest_paths_in_graph(); +template void export_dag_shortest_paths_in_graph(); +template void export_bellman_ford_shortest_paths_in_graph(); + template void export_prim_minimum_spanning_tree_in_graph(); +extern void export_connected_components(); +extern void export_strong_components(); extern void export_biconnected_components(); +extern void export_incremental_components(); +extern void export_topological_sort(); +extern void export_circle_graph_layout(); +extern void export_fruchterman_reingold_force_directed_layout(); +extern void export_kamada_kawai_spring_layout(); +extern void export_kruskal_minimum_spanning_tree(); +extern void export_transitive_closure(); + //extern void export_transpose_graph(); +extern void export_isomorphism(); template void export_in_graph() { export_breadth_first_search_in_graph(); + export_depth_first_search_in_graph(); export_dijkstra_shortest_paths_in_graph(); + export_bellman_ford_shortest_paths_in_graph(); + export_dag_shortest_paths_in_graph(); + export_prim_minimum_spanning_tree_in_graph(); } BOOST_PYTHON_MODULE(bgl) { + using boost::python::class_; + using boost::python::enum_; + enum_("file_kind") .value("adjlist", gfk_adjlist) .value("graphviz", gfk_graphviz) @@ -45,21 +70,39 @@ BOOST_PYTHON_MODULE(bgl) .value("black", color_traits::black()) ; -#if 0 class_("Point2D") - .def("x", &point2d::x) - .def("y", &point2d::y) + .def_readwrite("x", &point2d::x) + .def_readwrite("y", &point2d::y) ; -#endif export_Graph(); export_Digraph(); export_betweenness_centrality(); export_page_rank(); - export_done(); + // Core Algorithm Patterns export_breadth_first_search(); + export_depth_first_search(); + // Shortest Paths Algorithms export_dijkstra_shortest_paths(); - export_biconnected_components(); + export_bellman_ford_shortest_paths(); + export_dag_shortest_paths(); + // Minimum Spanning Tree Algorithms + export_kruskal_minimum_spanning_tree(); + export_prim_minimum_spanning_tree(); + // Connected Components Algorithms + export_connected_components(); + export_strong_components(); + export_biconnected_components(); + export_incremental_components(); + // Layout Algorithms + export_circle_graph_layout(); + export_fruchterman_reingold_force_directed_layout(); + export_kamada_kawai_spring_layout(); + // Other algorithms + export_topological_sort(); + export_transitive_closure(); + // export_transpose_graph(); + export_isomorphism(); } template void export_in_graph(); diff --git a/src/python/page_rank.cpp b/src/python/page_rank.cpp index d4e3d5cc..67d36184 100644 --- a/src/python/page_rank.cpp +++ b/src/python/page_rank.cpp @@ -8,67 +8,73 @@ // Andrew Lumsdaine #include "digraph.hpp" #include -#include "done.hpp" namespace boost { namespace graph { namespace python { - - template void -page_rank_ri +page_rank_iterations (Graph& g, - const vector_property_map& rank, + const vector_property_map* in_rank, int iterations) { - boost::graph::page_rank(g, rank, graph::n_iterations(20)); -} + typedef vector_property_map + RankMap; -template -void -page_rank_i(Graph& g, int iterations) -{ - boost::graph::page_rank(g, g.template get_vertex_map("rank"), - graph::n_iterations(20)); + RankMap rank = + in_rank? *in_rank : g.template get_vertex_map("pagerank"); + + boost::graph::page_rank(g, rank, graph::n_iterations(20)); } struct page_rank_wrap_done { - page_rank_wrap_done(const done& d) : d(d) { } + page_rank_wrap_done(boost::python::object done) : done(done) { } template bool - operator()(const RankMap&, const Graph&) const + operator()(const RankMap& rank, const Graph& g) const { - return d(); + using boost::python::extract; + return extract(done(rank, g)); } - const done& d; +private: + boost::python::object done; }; + template void -page_rank_rd +page_rank_done (Graph& g, - const vector_property_map& rank, - const done& d) + const vector_property_map* in_rank, + boost::python::object done) { - boost::graph::page_rank(g, rank, page_rank_wrap_done(d)); -} + typedef vector_property_map + RankMap; -template -void page_rank_d(Graph& g, const done& d) -{ - boost::graph::page_rank(g, g.template get_vertex_map("rank"), - page_rank_wrap_done(d)); + RankMap rank = + in_rank? *in_rank : g.template get_vertex_map("pagerank"); + + boost::graph::page_rank(g, rank, wrap_pr_done(done)); } void export_page_rank() { - def("page_rank", &page_rank_i); - def("page_rank", &page_rank_ri); - def("page_rank", &page_rank_rd); - def("page_rank", &page_rank_d); + using boost::python::arg; + using boost::python::def; + + def("page_rank", &page_rank_iterations, + (arg("graph"), + arg("rank_map") = + (vector_property_map*)0, + arg("iterations") = 20)); + def("page_rank", &page_rank_iterations, + (arg("graph"), + arg("rank_map") = + (vector_property_map*)0, + arg("done"))); } diff --git a/src/python/prim_minimum_spanning_tree.cpp b/src/python/prim_minimum_spanning_tree.cpp new file mode 100644 index 00000000..d7f17d0f --- /dev/null +++ b/src/python/prim_minimum_spanning_tree.cpp @@ -0,0 +1,105 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include +#include "dijkstra_visitor.hpp" + +namespace boost { namespace graph { namespace python { + +template +void +prim_minimum_spanning_tree + (Graph& g, typename Graph::Vertex s, + const vector_property_map* in_predecessor, + const vector_property_map* in_distance, + const vector_property_map* in_weight, + const dijkstra_visitor& visitor) +{ + typedef vector_property_map + PredecessorMap; + typedef vector_property_map + DistanceMap; + typedef vector_property_map + WeightMap; + + PredecessorMap predecessor = + in_predecessor? *in_predecessor + : PredecessorMap(g.num_vertices(), g.get_vertex_index_map()); + + DistanceMap distance = + in_distance? *in_distance + : DistanceMap(g.num_vertices(), g.get_vertex_index_map()); + + WeightMap weight = in_weight? *in_weight + : g.template get_edge_map("weight"); + + typedef typename dijkstra_visitor::default_arg default_visitor; + bool has_default_visitor = dynamic_cast(&visitor); + + if (!has_default_visitor) { + boost::prim_minimum_spanning_tree + (g, + predecessor, + root_vertex(s). + vertex_index_map(g.get_vertex_index_map()). + visitor(typename dijkstra_visitor::ref(visitor)). + distance_map(distance). + weight_map(weight)); + } else { + boost::prim_minimum_spanning_tree + (g, + predecessor, + root_vertex(s). + vertex_index_map(g.get_vertex_index_map()). + distance_map(distance). + weight_map(weight)); + } +} + +template +void export_prim_minimum_spanning_tree_in_graph() +{ + dijkstra_visitor::declare("DijkstraVisitor", + "DefaultDijkstraVisitor"); +} + +void export_prim_minimum_spanning_tree() +{ + using boost::python::arg; + using boost::python::def; + + def("prim_minimum_spanning_tree", &prim_minimum_spanning_tree, + (arg("graph"), arg("root_vertex"), + arg("predecessor_map") = + (vector_property_map*)0, + arg("distance_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0, + arg("visitor") = dijkstra_visitor::default_arg())); + + def("prim_minimum_spanning_tree", &prim_minimum_spanning_tree, + (arg("graph"), arg("root_vertex"), + arg("predecessor_map") = + (vector_property_map*)0, + arg("distance_map") = + (vector_property_map*)0, + arg("weight_map") = + (vector_property_map*)0, + arg("visitor") = dijkstra_visitor::default_arg())); +} + +template void export_prim_minimum_spanning_tree_in_graph(); +template void export_prim_minimum_spanning_tree_in_graph(); + +} } } // end namespace boost::graph::python diff --git a/src/python/queue.hpp b/src/python/queue.hpp index 8086c42b..1c4b8ab4 100644 --- a/src/python/queue.hpp +++ b/src/python/queue.hpp @@ -43,9 +43,14 @@ class python_queue static void declare(const char* name, const char* default_name) { - using namespace boost::python; + using boost::python::objects::registered_class_object; + using boost::python::type_id; + using boost::python::class_; + using boost::python::bases; + using boost::python::no_init; + using boost::python::pure_virtual; - if (objects::registered_class_object(type_id()).get() == 0) { + if (registered_class_object(type_id()).get() == 0) { class_(name) .def("empty", pure_virtual(&python_queue::empty)) .def("top", pure_virtual(&python_queue::top)) @@ -54,7 +59,7 @@ class python_queue ; } - if (objects::registered_class_object(type_id()).get() == 0) + if (registered_class_object(type_id()).get() == 0) { class_ >(default_name, no_init); } diff --git a/src/python/strong_components.cpp b/src/python/strong_components.cpp new file mode 100644 index 00000000..8b02d45b --- /dev/null +++ b/src/python/strong_components.cpp @@ -0,0 +1,42 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include + +namespace boost { namespace graph { namespace python { + +template +int +strong_components + (Graph& g, + const vector_property_map* in_component) +{ + typedef vector_property_map ComponentMap; + + ComponentMap component = + in_component? *in_component : g.template get_vertex_map("component"); + + return boost::strong_components (g, component, + vertex_index_map(g.get_vertex_index_map())); +} + +void export_strong_components() +{ + using boost::python::arg; + using boost::python::def; + + def("strong_components", &strong_components, + (arg("graph"), + arg("component_map") = + (vector_property_map*)0)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/topological_sort.cpp b/src/python/topological_sort.cpp new file mode 100644 index 00000000..e1979e7e --- /dev/null +++ b/src/python/topological_sort.cpp @@ -0,0 +1,55 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include +#include +#include + +namespace boost { namespace graph { namespace python { + +template +boost::python::list +topological_sort + (const Graph& g, + const vector_property_map* in_color) +{ + typedef vector_property_map ColorMap; + + ColorMap color = + in_color? *in_color : ColorMap(g.num_vertices(), g.get_vertex_index_map()); + + std::list topo_order; + boost::python::list result; + boost::topological_sort(g, std::back_inserter(topo_order), color_map(color)); + for (typename std::list::iterator i + = topo_order.begin(); i != topo_order.end(); ++i) + result.append(*i); + return result; +} + +void export_topological_sort() +{ + using boost::python::arg; + using boost::python::def; + + def("topological_sort", &topological_sort, + (arg("graph"), + arg("color_map") = + (vector_property_map*)0)); + def("topological_sort", &topological_sort, + (arg("graph"), + arg("color_map") = + (vector_property_map*)0)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/transitive_closure.cpp b/src/python/transitive_closure.cpp new file mode 100644 index 00000000..1527164f --- /dev/null +++ b/src/python/transitive_closure.cpp @@ -0,0 +1,45 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#include +#include "graph.hpp" +#include "digraph.hpp" +#include +#include +#include + +namespace boost { namespace graph { namespace python { + +template +std::auto_ptr +transitive_closure + (const Graph& g, + const vector_property_map* g_to_tc_map) +{ + std::auto_ptr tc(new Graph); + if (g_to_tc_map) + boost::transitive_closure(g, *tc, *g_to_tc_map, g.get_vertex_index_map()); + else + boost::transitive_closure(g, *tc, + vertex_index_map(g.get_vertex_index_map())); + return tc; +} + +void export_transitive_closure() +{ + using boost::python::arg; + using boost::python::def; + + def("transitive_closure", &transitive_closure, + (arg("graph"), + arg("g_to_tc_map") = + (vector_property_map*)0)); +} + +} } } // end namespace boost::graph::python diff --git a/src/python/visitor.hpp b/src/python/visitor.hpp index c8c08256..34d805b2 100644 --- a/src/python/visitor.hpp +++ b/src/python/visitor.hpp @@ -20,9 +20,9 @@ class BGL_PYTHON_VISITOR #define BGL_PYTHON_EVENT(Name,Descriptor) \ void Name(Descriptor x, const Graph& g) const \ { \ - if (override f = this->get_override(#Name)) \ + if (boost::python::override f = this->get_override(#Name)) \ f(x, boost::cref(g)); \ - else BGL_PYTHON_VISITOR::Name(x, g); \ + else BGL_PYTHON_VISITOR::Name(x, g); \ } \ \ void default_##Name(Descriptor x, const Graph& g) const \ @@ -62,6 +62,15 @@ class BGL_PYTHON_VISITOR static void declare(const char* name, const char* default_name) { + using boost::python::class_; + using boost::python::bases; + using boost::python::no_init; + using boost::python::objects::registered_class_object; + using boost::python::type_id; + + if (registered_class_object(type_id()).get() != 0) + return; + #define BGL_PYTHON_EVENT(Name, Descriptor) \ .def(#Name, &BGL_PYTHON_VISITOR::Name, &wrap::default_##Name) class_(name)