mirror of
https://github.com/boostorg/graph.git
synced 2026-01-28 07:12:14 +00:00
Initial version
[SVN r27536]
This commit is contained in:
538
src/python/basic_graph.cpp
Normal file
538
src/python/basic_graph.cpp
Normal file
@@ -0,0 +1,538 @@
|
||||
#include "basic_graph.hpp"
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
class copying_dynamic_property_map
|
||||
{
|
||||
public:
|
||||
virtual ~copying_dynamic_property_map() {}
|
||||
|
||||
virtual void copy_value(const any& to, const any& from) = 0;
|
||||
};
|
||||
|
||||
template<typename PropertyMap>
|
||||
class copying_dynamic_adaptor
|
||||
: public boost::detail::dynamic_property_map_adaptor<PropertyMap>,
|
||||
public copying_dynamic_property_map
|
||||
{
|
||||
typedef boost::detail::dynamic_property_map_adaptor<PropertyMap> inherited;
|
||||
|
||||
public:
|
||||
typedef typename property_traits<PropertyMap>::key_type key_type;
|
||||
|
||||
explicit copying_dynamic_adaptor(const PropertyMap& property_map)
|
||||
: inherited(property_map) { }
|
||||
|
||||
virtual void copy_value(const any& to, const any& from)
|
||||
{
|
||||
boost::put(this->base(), any_cast<key_type>(to),
|
||||
boost::get(this->base(), any_cast<key_type>(from)));
|
||||
}
|
||||
};
|
||||
|
||||
template<typename DirectedS>
|
||||
struct build_string_property_maps
|
||||
{
|
||||
build_string_property_maps(basic_graph<DirectedS>* g) : g(g) { }
|
||||
|
||||
std::auto_ptr<boost::dynamic_property_map>
|
||||
operator()(const std::string& name, const boost::any& key,
|
||||
const boost::any& value)
|
||||
{
|
||||
typedef typename basic_graph<DirectedS>::VertexIndexMap VertexIndexMap;
|
||||
typedef typename basic_graph<DirectedS>::EdgeIndexMap EdgeIndexMap;
|
||||
|
||||
std::auto_ptr<boost::dynamic_property_map> result(0);
|
||||
|
||||
if (key.type() == typeid(typename basic_graph<DirectedS>::Vertex)) {
|
||||
typedef vector_property_map<std::string, VertexIndexMap>
|
||||
property_map_type;
|
||||
typedef copying_dynamic_adaptor<property_map_type> adaptor_type;
|
||||
result.reset
|
||||
(new adaptor_type(property_map_type(g->num_vertices(),
|
||||
g->get_vertex_index_map())));
|
||||
} else if (key.type() == typeid(typename basic_graph<DirectedS>::Edge)) {
|
||||
typedef vector_property_map<std::string, EdgeIndexMap> property_map_type;
|
||||
typedef copying_dynamic_adaptor<property_map_type> adaptor_type;
|
||||
result.reset
|
||||
(new adaptor_type(property_map_type(g->num_edges(),
|
||||
g->get_edge_index_map())));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
basic_graph<DirectedS>* g;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Constructors
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
basic_graph<DirectedS>::basic_graph()
|
||||
: inherited(), dp(build_string_property_maps<DirectedS>(this))
|
||||
{ }
|
||||
|
||||
template<typename DirectedS>
|
||||
basic_graph<DirectedS>::basic_graph(const std::string& filename,
|
||||
graph_file_kind kind)
|
||||
: inherited(), dp(build_string_property_maps<DirectedS>(this))
|
||||
{
|
||||
switch (kind) {
|
||||
case gfk_adjlist:
|
||||
break;
|
||||
case gfk_graphviz:
|
||||
read_graphviz(filename);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Incidence basic_graph<DirectedS> concept
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::Vertex
|
||||
basic_graph<DirectedS>::source(Edge e) const
|
||||
{ return Vertex(boost::source(e.base, base())); }
|
||||
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::Vertex
|
||||
basic_graph<DirectedS>::target(Edge e) const
|
||||
{ return Vertex(boost::target(e.base, base())); }
|
||||
|
||||
|
||||
template<typename DirectedS>
|
||||
std::pair<typename basic_graph<DirectedS>::out_edge_iterator,
|
||||
typename basic_graph<DirectedS>::out_edge_iterator>
|
||||
basic_graph<DirectedS>::out_edges(Vertex u) const
|
||||
{
|
||||
std::pair<base_out_edge_iterator, base_out_edge_iterator> rng =
|
||||
boost::out_edges(u.base, base());
|
||||
return std::make_pair(out_edge_iterator(rng.first, Edge::create()),
|
||||
out_edge_iterator(rng.second, Edge::create()));
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
simple_python_iterator<typename basic_graph<DirectedS>::out_edge_iterator>
|
||||
basic_graph<DirectedS>::py_out_edges(Vertex u) const
|
||||
{
|
||||
return simple_python_iterator<out_edge_iterator>(out_edges(u));
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
std::size_t
|
||||
basic_graph<DirectedS>::out_degree(Vertex u) const
|
||||
{
|
||||
return boost::out_degree(u.base, base());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Bidirectional basic_graph<DirectedS> concept
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
std::pair<typename basic_graph<DirectedS>::in_edge_iterator,
|
||||
typename basic_graph<DirectedS>::in_edge_iterator>
|
||||
basic_graph<DirectedS>::in_edges(Vertex u) const
|
||||
{
|
||||
std::pair<base_in_edge_iterator, base_in_edge_iterator> rng =
|
||||
boost::in_edges(u.base, base());
|
||||
return std::make_pair(in_edge_iterator(rng.first, Edge::create()),
|
||||
in_edge_iterator(rng.second, Edge::create()));
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
simple_python_iterator<typename basic_graph<DirectedS>::in_edge_iterator>
|
||||
basic_graph<DirectedS>::py_in_edges(Vertex u) const
|
||||
{
|
||||
return simple_python_iterator<in_edge_iterator>(in_edges(u));
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
std::size_t
|
||||
basic_graph<DirectedS>::in_degree(Vertex u) const
|
||||
{
|
||||
return boost::in_degree(u.base, base());
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Adjacency basic_graph<DirectedS> concept
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
std::pair<typename basic_graph<DirectedS>::adjacency_iterator,
|
||||
typename basic_graph<DirectedS>::adjacency_iterator>
|
||||
basic_graph<DirectedS>::adjacent_vertices(Vertex u) const
|
||||
{
|
||||
std::pair<base_adjacency_iterator, base_adjacency_iterator> rng =
|
||||
boost::adjacent_vertices(u.base, base());
|
||||
return std::make_pair(adjacency_iterator(rng.first, Vertex::create()),
|
||||
adjacency_iterator(rng.second, Vertex::create()));
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
simple_python_iterator<typename basic_graph<DirectedS>::adjacency_iterator>
|
||||
basic_graph<DirectedS>::py_adjacent_vertices(Vertex u) const
|
||||
{
|
||||
return
|
||||
simple_python_iterator<adjacency_iterator>(adjacent_vertices(u));
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Vertex properties
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
template<typename T>
|
||||
vector_property_map<T, typename basic_graph<DirectedS>::VertexIndexMap>
|
||||
basic_graph<DirectedS>::get_vertex_map(const std::string& name)
|
||||
{
|
||||
typedef vector_property_map<T, VertexIndexMap> result_type;
|
||||
typedef copying_dynamic_adaptor<result_type> adaptor_type;
|
||||
|
||||
dynamic_properties::iterator i = dp.lower_bound(name);
|
||||
while (i != dp.end() && i->first == name) {
|
||||
if (i->second->key() == typeid(Vertex)) {
|
||||
if (i->second->value() == typeid(T)) {
|
||||
return dynamic_cast<adaptor_type&>(*i->second).base();
|
||||
} else {
|
||||
// Convert the property map element-by-element to the
|
||||
// requested type.
|
||||
result_type result(num_vertices(), get_vertex_index_map());
|
||||
for(vertex_iterator v = vertices().first; v != vertices().second;
|
||||
++v) {
|
||||
put(result, *v, lexical_cast<T>(i->second->get_string(*v)));
|
||||
}
|
||||
|
||||
// Replace the existing property map with the converted one
|
||||
adaptor_type* adaptor = new adaptor_type(result);
|
||||
delete i->second;
|
||||
i->second = adaptor;
|
||||
|
||||
// Return the new property map.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
typedef vector_property_map<T, VertexIndexMap> property_map_type;
|
||||
typedef copying_dynamic_adaptor<property_map_type> adaptor_type;
|
||||
property_map_type result(num_vertices(), get_vertex_index_map());
|
||||
dp.insert(name,
|
||||
std::auto_ptr<dynamic_property_map>(new adaptor_type(result)));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
bool
|
||||
basic_graph<DirectedS>::has_vertex_map(const std::string& name) const
|
||||
{
|
||||
dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
while (i != dp.end() && i->first == name) {
|
||||
if (i->second->key() == typeid(Vertex))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Edge properties
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
template<typename T>
|
||||
vector_property_map<T, typename basic_graph<DirectedS>::EdgeIndexMap>
|
||||
basic_graph<DirectedS>::get_edge_map(const std::string& name)
|
||||
{
|
||||
typedef vector_property_map<T, EdgeIndexMap> result_type;
|
||||
typedef copying_dynamic_adaptor<result_type> adaptor_type;
|
||||
|
||||
dynamic_properties::iterator i = dp.lower_bound(name);
|
||||
while (i != dp.end() && i->first == name) {
|
||||
if (i->second->key() == typeid(Edge)) {
|
||||
if (i->second->value() == typeid(T)) {
|
||||
return dynamic_cast<adaptor_type&>(*i->second).base();
|
||||
} else {
|
||||
// Convert the property map element-by-element to the
|
||||
// requested type.
|
||||
result_type result(num_vertices(), get_edge_index_map());
|
||||
for(edge_iterator e = edges().first; e != edges().second; ++e) {
|
||||
put(result, *e, lexical_cast<T>(i->second->get_string(*e)));
|
||||
}
|
||||
|
||||
// Replace the existing property map with the converted one
|
||||
adaptor_type* adaptor = new adaptor_type(result);
|
||||
delete i->second;
|
||||
i->second = adaptor;
|
||||
|
||||
// Return the new property map.
|
||||
return result;
|
||||
}
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
typedef vector_property_map<T, EdgeIndexMap> property_map_type;
|
||||
typedef copying_dynamic_adaptor<property_map_type> adaptor_type;
|
||||
property_map_type result(num_edges(), get_edge_index_map());
|
||||
dp.insert(name,
|
||||
std::auto_ptr<dynamic_property_map>(new adaptor_type(result)));
|
||||
return result;
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
bool
|
||||
basic_graph<DirectedS>::has_edge_map(const std::string& name) const
|
||||
{
|
||||
dynamic_properties::const_iterator i = dp.lower_bound(name);
|
||||
while (i != dp.end() && i->first == name) {
|
||||
if (i->second->key() == typeid(Edge))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------
|
||||
// Mutable graph
|
||||
// ----------------------------------------------------------
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::Vertex basic_graph<DirectedS>::add_vertex()
|
||||
{
|
||||
using boost::add_vertex;
|
||||
|
||||
base_vertex_descriptor v = add_vertex(base());
|
||||
put(vertex_index, base(), v, index_to_vertex.size());
|
||||
index_to_vertex.push_back(v);
|
||||
return Vertex(v);
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
void basic_graph<DirectedS>::clear_vertex(Vertex vertex)
|
||||
{
|
||||
// Remove all incoming and outgoing edges
|
||||
while (out_degree(vertex) > 0) remove_edge(*out_edges(vertex).first);
|
||||
while (in_degree(vertex) > 0) remove_edge(*in_edges(vertex).first);
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
void basic_graph<DirectedS>::remove_vertex(Vertex vertex)
|
||||
{
|
||||
using boost::remove_vertex;
|
||||
|
||||
// Update property maps
|
||||
for (dynamic_properties::iterator i = dp.begin(); i != dp.end(); ++i) {
|
||||
if (i->second->key() == typeid(Vertex)) {
|
||||
dynamic_cast<copying_dynamic_property_map&>(*i->second).
|
||||
copy_value(vertex, Vertex(index_to_vertex.back()));
|
||||
}
|
||||
}
|
||||
|
||||
// Update vertex indices
|
||||
std::size_t index = get(vertex_index, base(), vertex.base);
|
||||
index_to_vertex[index] = index_to_vertex.back();
|
||||
put(vertex_index, base(), index_to_vertex[index], index);
|
||||
index_to_vertex.pop_back();
|
||||
|
||||
// Remove the actual vertex
|
||||
remove_vertex(vertex.base, base());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
std::size_t basic_graph<DirectedS>::num_vertices() const
|
||||
{
|
||||
using boost::num_vertices;
|
||||
return num_vertices(base());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::vertex_iterator
|
||||
basic_graph<DirectedS>::vertices_begin() const
|
||||
{
|
||||
return make_transform_iterator(boost::vertices(base()).first,
|
||||
Vertex::create());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::vertex_iterator
|
||||
basic_graph<DirectedS>::vertices_end() const
|
||||
{
|
||||
return make_transform_iterator(boost::vertices(base()).second,
|
||||
Vertex::create());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
std::pair<typename basic_graph<DirectedS>::vertex_iterator,
|
||||
typename basic_graph<DirectedS>::vertex_iterator>
|
||||
basic_graph<DirectedS>::vertices() const
|
||||
{
|
||||
return std::make_pair(vertices_begin(), vertices_end());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::Edge
|
||||
basic_graph<DirectedS>::add_edge(Vertex u, Vertex v)
|
||||
{
|
||||
using boost::add_edge;
|
||||
|
||||
base_edge_descriptor e = add_edge(u.base, v.base, base()).first;
|
||||
put(edge_index, base(), e, index_to_edge.size());
|
||||
index_to_edge.push_back(e);
|
||||
return Edge(e);
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
void basic_graph<DirectedS>::remove_edge(Edge edge)
|
||||
{
|
||||
using boost::remove_edge;
|
||||
|
||||
// Update property maps
|
||||
for (dynamic_properties::iterator i = dp.begin(); i != dp.end(); ++i) {
|
||||
if (i->second->key() == typeid(Edge)) {
|
||||
dynamic_cast<copying_dynamic_property_map&>(*i->second).
|
||||
copy_value(edge, Edge(index_to_edge.back()));
|
||||
}
|
||||
}
|
||||
|
||||
// Update edge indices
|
||||
std::size_t index = get(edge_index, base(), edge.base);
|
||||
index_to_edge[index] = index_to_edge.back();
|
||||
put(edge_index, base(), index_to_edge[index], index);
|
||||
index_to_edge.pop_back();
|
||||
|
||||
// Remove the actual edge
|
||||
remove_edge(edge.base, base());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
std::size_t basic_graph<DirectedS>::num_edges() const
|
||||
{
|
||||
using boost::num_edges;
|
||||
return num_edges(base());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::edge_iterator
|
||||
basic_graph<DirectedS>::edges_begin() const
|
||||
{
|
||||
return make_transform_iterator(boost::edges(base()).first,
|
||||
Edge::create());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
typename basic_graph<DirectedS>::edge_iterator
|
||||
basic_graph<DirectedS>::edges_end() const
|
||||
{
|
||||
return make_transform_iterator(boost::edges(base()).second,
|
||||
Edge::create());
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
std::pair<typename basic_graph<DirectedS>::edge_iterator,
|
||||
typename basic_graph<DirectedS>::edge_iterator>
|
||||
basic_graph<DirectedS>::edges() const
|
||||
{
|
||||
return std::make_pair(edges_begin(), edges_end());
|
||||
}
|
||||
|
||||
template<typename Graph> void export_in_graph();
|
||||
|
||||
template<typename DirectedS>
|
||||
void export_basic_graph(const char* name)
|
||||
{
|
||||
typedef basic_graph<DirectedS> Graph;
|
||||
typedef typename Graph::Vertex Vertex;
|
||||
typedef typename Graph::Edge Edge;
|
||||
typedef typename Graph::VertexIndexMap VertexIndexMap;
|
||||
typedef typename Graph::EdgeIndexMap EdgeIndexMap;
|
||||
|
||||
{
|
||||
scope s(
|
||||
class_<basic_graph<DirectedS> >(name)
|
||||
// Constructors
|
||||
.def(init<std::string, graph_file_kind>())
|
||||
// Vertex List Graph concept
|
||||
.def("num_vertices", &Graph::num_vertices)
|
||||
.add_property("vertices", range(&Graph::vertices_begin,
|
||||
&Graph::vertices_end))
|
||||
// Edge List Graph concept
|
||||
.def("num_edges", &Graph::num_edges)
|
||||
.add_property("edges", range(&Graph::edges_begin, &Graph::edges_end))
|
||||
// Mutable Graph concept
|
||||
.def("add_vertex", &Graph::add_vertex)
|
||||
.def("clear_vertex", &Graph::clear_vertex)
|
||||
.def("remove_vertex", &Graph::remove_vertex)
|
||||
.def("add_edge", &Graph::add_edge)
|
||||
.def("remove_edge", &Graph::remove_edge)
|
||||
// Incidence Graph concept
|
||||
.def("source", &Graph::source)
|
||||
.def("target", &Graph::target)
|
||||
.def("out_edges", &Graph::py_out_edges)
|
||||
.def("out_degree", &Graph::out_degree)
|
||||
.def("in_edges", &Graph::py_in_edges)
|
||||
.def("in_degree", &Graph::in_degree)
|
||||
.def("adjacent_vertices", &Graph::py_adjacent_vertices)
|
||||
// Vertex property maps
|
||||
.def("has_vertex_map", &Graph::has_vertex_map)
|
||||
.def("get_vertex_index_map", &Graph::get_vertex_index_map)
|
||||
.def("get_vertex_double_map", &Graph::template get_vertex_map<double>)
|
||||
.def("get_vertex_int_map", &Graph::template get_vertex_map<int>)
|
||||
.def("get_vertex_string_map",
|
||||
&Graph::template get_vertex_map<std::string>)
|
||||
.def("get_vertex_object_map", &Graph::template get_vertex_map<object>)
|
||||
// Edge property maps
|
||||
.def("has_edge_map", &Graph::has_vertex_map)
|
||||
.def("get_edge_index_map", &Graph::get_edge_index_map)
|
||||
.def("get_edge_double_map", &Graph::template get_edge_map<double>)
|
||||
.def("get_edge_int_map", &Graph::template get_edge_map<int>)
|
||||
.def("get_edge_string_map", &Graph::template get_edge_map<std::string>)
|
||||
.def("get_edge_object_map", &Graph::template get_edge_map<object>)
|
||||
// Graph I/O
|
||||
.def("read_graphviz", &Graph::read_graphviz)
|
||||
.def("write_graphviz", &Graph::write_graphviz)
|
||||
.def("write_graphviz", &Graph::write_graphviz_def)
|
||||
);
|
||||
|
||||
export_in_graph<Graph>();
|
||||
}
|
||||
|
||||
if (!type_already_registered<Vertex>())
|
||||
class_<Vertex>("Vertex")
|
||||
.def(self == self)
|
||||
.def(self != self);
|
||||
|
||||
if (!type_already_registered<Edge>())
|
||||
class_<Edge>("Edge")
|
||||
.def(self == self)
|
||||
.def(self != self);
|
||||
|
||||
// Iterators
|
||||
simple_python_iterator<typename Graph::out_edge_iterator>
|
||||
::declare("out_edge_iterator");
|
||||
simple_python_iterator<typename Graph::in_edge_iterator>
|
||||
::declare("in_edge_iterator");
|
||||
simple_python_iterator<typename Graph::adjacency_iterator>
|
||||
::declare("adjacency_iterator");
|
||||
|
||||
// Vertex property maps
|
||||
declare_readable_property_map<VertexIndexMap>
|
||||
::declare("vertex_index_map");
|
||||
declare_property_map<vector_property_map<double, VertexIndexMap> >
|
||||
::declare("vertex_double_map");
|
||||
declare_property_map<vector_property_map<int, VertexIndexMap> >
|
||||
::declare("vertex_int_map");
|
||||
declare_property_map<vector_property_map<std::string, VertexIndexMap> >
|
||||
::declare("vertex_string_map");
|
||||
declare_property_map<vector_property_map<object, VertexIndexMap> >
|
||||
::declare("vertex_object_map");
|
||||
|
||||
// Edge property maps
|
||||
declare_readable_property_map<EdgeIndexMap>
|
||||
::declare("edge_index_map");
|
||||
declare_property_map<vector_property_map<double, EdgeIndexMap> >
|
||||
::declare("edge_double_map");
|
||||
declare_property_map<vector_property_map<int, EdgeIndexMap> >
|
||||
::declare("edge_int_map");
|
||||
declare_property_map<vector_property_map<std::string, EdgeIndexMap> >
|
||||
::declare("edge_string_map");
|
||||
declare_property_map<vector_property_map<object, EdgeIndexMap> >
|
||||
::declare("edge_object_map");
|
||||
}
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
353
src/python/basic_graph.hpp
Normal file
353
src/python/basic_graph.hpp
Normal file
@@ -0,0 +1,353 @@
|
||||
#ifndef BOOST_GRAPH_BASIC_GRAPH_HPP
|
||||
#define BOOST_GRAPH_BASIC_GRAPH_HPP
|
||||
|
||||
#include <boost/graph/graph_traits.hpp>
|
||||
#include <boost/graph/adjacency_list.hpp>
|
||||
#include <boost/iterator/transform_iterator.hpp>
|
||||
#include <boost/vector_property_map.hpp>
|
||||
#include <boost/dynamic_property_map.hpp>
|
||||
#include <boost/python.hpp>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
template<typename T> bool type_already_registered()
|
||||
{
|
||||
return objects::registered_class_object(python::type_id<T>()).get() != 0;
|
||||
}
|
||||
|
||||
template<typename Iterator>
|
||||
class simple_python_iterator
|
||||
{
|
||||
public:
|
||||
simple_python_iterator(std::pair<Iterator, Iterator> p)
|
||||
: first(p.first), last(p.second) { }
|
||||
|
||||
typename std::iterator_traits<Iterator>::value_type next()
|
||||
{
|
||||
if (first == last) objects::stop_iteration_error();
|
||||
return *first++;
|
||||
}
|
||||
|
||||
static void declare(const char* name)
|
||||
{
|
||||
if (!type_already_registered<simple_python_iterator>())
|
||||
class_<simple_python_iterator<Iterator> >(name, no_init)
|
||||
.def("__iter__", objects::identity_function())
|
||||
.def("next", &simple_python_iterator<Iterator>::next)
|
||||
;
|
||||
}
|
||||
|
||||
private:
|
||||
Iterator first;
|
||||
Iterator last;
|
||||
};
|
||||
|
||||
template<typename PropertyMap>
|
||||
struct declare_readable_property_map
|
||||
{
|
||||
typedef typename property_traits<PropertyMap>::key_type key_type;
|
||||
typedef typename property_traits<PropertyMap>::value_type value_type;
|
||||
|
||||
static value_type getitem(const PropertyMap& pm, const key_type& key)
|
||||
{ return get(pm, key); }
|
||||
|
||||
static void declare(const char* name)
|
||||
{
|
||||
if (!type_already_registered<PropertyMap>())
|
||||
class_<PropertyMap>(name, no_init)
|
||||
.def("__getitem__", &getitem)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename PropertyMap>
|
||||
struct declare_property_map
|
||||
{
|
||||
typedef typename property_traits<PropertyMap>::key_type key_type;
|
||||
typedef typename property_traits<PropertyMap>::value_type value_type;
|
||||
|
||||
static value_type getitem(const PropertyMap& pm, const key_type& key)
|
||||
{ return get(pm, key); }
|
||||
|
||||
static void
|
||||
setitem(const PropertyMap& pm, const key_type& key,const value_type& value)
|
||||
{ return put(pm, key, value); }
|
||||
|
||||
static void declare(const char* name)
|
||||
{
|
||||
if (!type_already_registered<PropertyMap>())
|
||||
class_<PropertyMap>(name, no_init)
|
||||
.def("__getitem__", &getitem)
|
||||
.def("__setitem__", &setitem)
|
||||
;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct basic_descriptor
|
||||
{
|
||||
basic_descriptor() {}
|
||||
basic_descriptor(T base) : base(base) { }
|
||||
|
||||
operator T() const { return base; }
|
||||
|
||||
struct create
|
||||
{
|
||||
typedef basic_descriptor result_type;
|
||||
basic_descriptor operator()(T base) const { return base; }
|
||||
};
|
||||
|
||||
T base;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
operator==(const basic_descriptor<T>& u,
|
||||
const basic_descriptor<T>& v)
|
||||
{ return u.base == v.base; }
|
||||
|
||||
template<typename T>
|
||||
inline bool
|
||||
operator!=(const basic_descriptor<T>& u,
|
||||
const basic_descriptor<T>& v)
|
||||
{ return u.base != v.base; }
|
||||
|
||||
template<typename Key, typename IndexMap>
|
||||
struct basic_index_map
|
||||
{
|
||||
typedef Key key_type;
|
||||
typedef typename property_traits<IndexMap>::value_type value_type;
|
||||
typedef typename property_traits<IndexMap>::reference reference;
|
||||
typedef typename property_traits<IndexMap>::category category;
|
||||
|
||||
basic_index_map() {}
|
||||
basic_index_map(const IndexMap& id = IndexMap())
|
||||
: id(id) { }
|
||||
|
||||
IndexMap id;
|
||||
};
|
||||
|
||||
template<typename Key, typename IndexMap>
|
||||
inline typename basic_index_map<Key, IndexMap>::value_type
|
||||
get(const basic_index_map<Key, IndexMap>& pm,
|
||||
typename basic_index_map<Key, IndexMap>::key_type const& key)
|
||||
{ return get(pm.id, key.base); }
|
||||
|
||||
enum graph_file_kind { gfk_adjlist, gfk_graphviz };
|
||||
|
||||
template<typename DirectedS>
|
||||
class basic_graph
|
||||
: public adjacency_list<listS, listS, DirectedS,
|
||||
property<vertex_index_t, std::size_t>,
|
||||
property<edge_index_t, std::size_t> >
|
||||
{
|
||||
typedef adjacency_list<listS, listS, DirectedS,
|
||||
property<vertex_index_t, std::size_t>,
|
||||
property<edge_index_t, std::size_t> > inherited;
|
||||
typedef graph_traits<inherited> traits;
|
||||
|
||||
typedef typename traits::vertex_iterator base_vertex_iterator;
|
||||
typedef typename traits::edge_iterator base_edge_iterator;
|
||||
typedef typename traits::out_edge_iterator base_out_edge_iterator;
|
||||
typedef typename traits::in_edge_iterator base_in_edge_iterator;
|
||||
typedef typename traits::adjacency_iterator base_adjacency_iterator;
|
||||
typedef typename property_map<inherited, vertex_index_t>::const_type
|
||||
base_vertex_index_map;
|
||||
typedef typename property_map<inherited, edge_index_t>::const_type
|
||||
base_edge_index_map;
|
||||
typedef typename traits::vertex_descriptor base_vertex_descriptor;
|
||||
typedef typename traits::edge_descriptor base_edge_descriptor;
|
||||
|
||||
public:
|
||||
typedef basic_descriptor<base_vertex_descriptor> Vertex;
|
||||
typedef Vertex vertex_descriptor;
|
||||
typedef basic_descriptor<base_edge_descriptor> Edge;
|
||||
typedef Edge edge_descriptor;
|
||||
typedef basic_index_map<Vertex, base_vertex_index_map>
|
||||
VertexIndexMap;
|
||||
typedef basic_index_map<Edge, base_edge_index_map> EdgeIndexMap;
|
||||
typedef std::size_t vertices_size_type;
|
||||
typedef std::size_t edges_size_type;
|
||||
typedef std::size_t degree_size_type;
|
||||
typedef typename traits::directed_category directed_category;
|
||||
typedef typename traits::edge_parallel_category edge_parallel_category;
|
||||
typedef typename traits::traversal_category traversal_category;
|
||||
typedef transform_iterator<typename Vertex::create, base_vertex_iterator>
|
||||
vertex_iterator;
|
||||
typedef transform_iterator<typename Edge::create, base_edge_iterator>
|
||||
edge_iterator;
|
||||
typedef transform_iterator<typename Edge::create, base_out_edge_iterator>
|
||||
out_edge_iterator;
|
||||
typedef transform_iterator<typename Edge::create, base_in_edge_iterator>
|
||||
in_edge_iterator;
|
||||
typedef transform_iterator<typename Vertex::create, base_adjacency_iterator>
|
||||
adjacency_iterator;
|
||||
|
||||
basic_graph();
|
||||
basic_graph(const std::string& filename, graph_file_kind kind);
|
||||
|
||||
Vertex add_vertex();
|
||||
void clear_vertex(Vertex vertex);
|
||||
void remove_vertex(Vertex vertex);
|
||||
std::size_t num_vertices() const;
|
||||
std::pair<vertex_iterator, vertex_iterator> vertices() const;
|
||||
vertex_iterator vertices_begin() const;
|
||||
vertex_iterator vertices_end() const;
|
||||
|
||||
Edge add_edge(Vertex u, Vertex v);
|
||||
void remove_edge(Edge edge);
|
||||
std::size_t num_edges() const;
|
||||
std::pair<edge_iterator, edge_iterator> edges() const;
|
||||
edge_iterator edges_begin() const;
|
||||
edge_iterator edges_end() const;
|
||||
|
||||
// Incidence Graph concept
|
||||
Vertex source(Edge e) const;
|
||||
Vertex target(Edge e) const;
|
||||
std::pair<out_edge_iterator, out_edge_iterator> out_edges(Vertex u) const;
|
||||
simple_python_iterator<out_edge_iterator> py_out_edges(Vertex u) const;
|
||||
std::size_t out_degree(Vertex u) const;
|
||||
|
||||
// Bidirectional Graph concept
|
||||
std::pair<in_edge_iterator, in_edge_iterator> in_edges(Vertex u) const;
|
||||
simple_python_iterator<in_edge_iterator> py_in_edges(Vertex u) const;
|
||||
std::size_t in_degree(Vertex u) const;
|
||||
|
||||
// Adjacency Graph concept
|
||||
std::pair<adjacency_iterator, adjacency_iterator>
|
||||
adjacent_vertices(Vertex u) const;
|
||||
|
||||
simple_python_iterator<adjacency_iterator>
|
||||
py_adjacent_vertices(Vertex u) const;
|
||||
|
||||
// Vertex property maps
|
||||
VertexIndexMap get_vertex_index_map() const
|
||||
{ return get(vertex_index, base()); }
|
||||
|
||||
template<typename T>
|
||||
vector_property_map<T, VertexIndexMap>
|
||||
get_vertex_map(const std::string& name);
|
||||
|
||||
bool has_vertex_map(const std::string& name) const;
|
||||
|
||||
// Edge property maps
|
||||
EdgeIndexMap get_edge_index_map() const
|
||||
{ return get(edge_index, base()); }
|
||||
|
||||
template<typename T>
|
||||
vector_property_map<T, EdgeIndexMap>
|
||||
get_edge_map(const std::string& name);
|
||||
|
||||
bool has_edge_map(const std::string& name) const;
|
||||
|
||||
// Graph I/O
|
||||
void read_graphviz(const std::string& filename,
|
||||
const std::string& node_id = std::string("node_id"));
|
||||
|
||||
void write_graphviz(const std::string& filename,
|
||||
const std::string& node_id = std::string("node_id"));
|
||||
|
||||
void write_graphviz_def(const std::string& filename)
|
||||
{ write_graphviz(filename); }
|
||||
|
||||
|
||||
inherited& base() { return *this; }
|
||||
const inherited& base() const { return *this; }
|
||||
|
||||
private:
|
||||
std::vector<vertex_descriptor> index_to_vertex;
|
||||
std::vector<edge_descriptor> index_to_edge;
|
||||
dynamic_properties dp;
|
||||
};
|
||||
|
||||
// Vertex List Graph concept
|
||||
template<typename DirectedS>
|
||||
inline std::pair<typename basic_graph<DirectedS>::vertex_iterator,
|
||||
typename basic_graph<DirectedS>::vertex_iterator>
|
||||
vertices(const basic_graph<DirectedS>& g)
|
||||
{ return g.vertices(); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline std::size_t num_vertices(const basic_graph<DirectedS>& g)
|
||||
{ return g.num_vertices(); }
|
||||
|
||||
// Edge List Graph concept
|
||||
template<typename DirectedS>
|
||||
inline std::pair<typename basic_graph<DirectedS>::edge_iterator,
|
||||
typename basic_graph<DirectedS>::edge_iterator>
|
||||
edges(const basic_graph<DirectedS>& g)
|
||||
{ return g.edges(); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline std::size_t num_edges(const basic_graph<DirectedS>& g)
|
||||
{ return g.num_edges(); }
|
||||
|
||||
// Incidence Graph concept
|
||||
template<typename DirectedS>
|
||||
inline typename basic_graph<DirectedS>::vertex_descriptor
|
||||
source(typename basic_graph<DirectedS>::edge_descriptor e,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.source(e); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline typename basic_graph<DirectedS>::vertex_descriptor
|
||||
target(typename basic_graph<DirectedS>::edge_descriptor e,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.target(e); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline std::pair<typename basic_graph<DirectedS>::out_edge_iterator,
|
||||
typename basic_graph<DirectedS>::out_edge_iterator>
|
||||
out_edges(typename basic_graph<DirectedS>::vertex_descriptor u,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.out_edges(u); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline std::size_t
|
||||
out_degree(typename basic_graph<DirectedS>::vertex_descriptor u,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.out_degree(u); }
|
||||
|
||||
// Bidirectional Graph concept
|
||||
template<typename DirectedS>
|
||||
inline std::pair<typename basic_graph<DirectedS>::in_edge_iterator,
|
||||
typename basic_graph<DirectedS>::in_edge_iterator>
|
||||
in_edges(typename basic_graph<DirectedS>::vertex_descriptor u,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.in_edges(u); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline std::size_t
|
||||
in_degree(typename basic_graph<DirectedS>::vertex_descriptor u,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.in_degree(u); }
|
||||
|
||||
// Adjacency Graph concept
|
||||
template<typename DirectedS>
|
||||
inline std::pair<typename basic_graph<DirectedS>::adjacency_iterator,
|
||||
typename basic_graph<DirectedS>::adjacency_iterator>
|
||||
adjacent_vertices(typename basic_graph<DirectedS>::vertex_descriptor u,
|
||||
const basic_graph<DirectedS>& g)
|
||||
{ return g.adjacent_vertices(u); }
|
||||
|
||||
// Mutable basic_graph<DirectedS> concept
|
||||
template<typename DirectedS>
|
||||
inline typename basic_graph<DirectedS>::vertex_descriptor
|
||||
add_vertex(basic_graph<DirectedS>& g)
|
||||
{ return g.add_vertex(); }
|
||||
|
||||
template<typename DirectedS>
|
||||
inline std::pair<typename basic_graph<DirectedS>::edge_descriptor, bool>
|
||||
add_edge(typename basic_graph<DirectedS>::vertex_descriptor u,
|
||||
typename basic_graph<DirectedS>::vertex_descriptor v,
|
||||
basic_graph<DirectedS>& g)
|
||||
{ return std::make_pair(g.add_edge(u, v), true); }
|
||||
|
||||
template<typename DirectedS>
|
||||
void export_basic_graph(const char* name);
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
|
||||
#endif // BOOST_GRAPH_BASIC_GRAPH_HPP
|
||||
126
src/python/betweenness_centrality.cpp
Normal file
126
src/python/betweenness_centrality.cpp
Normal file
@@ -0,0 +1,126 @@
|
||||
#include "graph.hpp"
|
||||
#include "digraph.hpp"
|
||||
#include <boost/graph/betweenness_centrality.hpp>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
template<typename Graph>
|
||||
void
|
||||
brandes_betweenness_centrality_ve
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::VertexIndexMap>& vertex_centrality,
|
||||
const vector_property_map<double, typename Graph::EdgeIndexMap>& edge_centrality)
|
||||
{
|
||||
brandes_betweenness_centrality
|
||||
(g,
|
||||
centrality_map(vertex_centrality).
|
||||
edge_centrality_map(edge_centrality).
|
||||
vertex_index_map(g.get_vertex_index_map()));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
brandes_betweenness_centrality_v
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::VertexIndexMap>& vertex_centrality)
|
||||
{
|
||||
brandes_betweenness_centrality_ve(g, vertex_centrality,
|
||||
g.template get_edge_map<double>("centrality"));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void
|
||||
brandes_betweenness_centrality_wve
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::EdgeIndexMap>& weight,
|
||||
const vector_property_map<double, typename Graph::VertexIndexMap>& vertex_centrality,
|
||||
const vector_property_map<double, typename Graph::EdgeIndexMap>& 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()));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
brandes_betweenness_centrality_wv
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::EdgeIndexMap>& weight,
|
||||
const vector_property_map<double, typename Graph::VertexIndexMap>& vertex_centrality)
|
||||
{
|
||||
brandes_betweenness_centrality_wve(g, weight, vertex_centrality,
|
||||
g.template get_edge_map<double>("centrality"));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
brandes_betweenness_centrality_w
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::EdgeIndexMap>& weight)
|
||||
{
|
||||
brandes_betweenness_centrality_wv(g, weight,
|
||||
g.template get_vertex_map<double>("centrality"));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
inline void
|
||||
brandes_betweenness_centrality(Graph& g)
|
||||
{
|
||||
brandes_betweenness_centrality_v(g, g.template get_vertex_map<double>("centrality"));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void
|
||||
relative_betweenness_centrality
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::VertexIndexMap>& centrality)
|
||||
{ relative_betweenness_centrality(g, centrality); }
|
||||
|
||||
template<typename Graph>
|
||||
double
|
||||
central_point_dominance
|
||||
(Graph& g,
|
||||
const vector_property_map<double, typename Graph::VertexIndexMap>& centrality)
|
||||
{ return boost::central_point_dominance(g, centrality); }
|
||||
|
||||
void export_betweenness_centrality()
|
||||
{
|
||||
// Graph
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality<Graph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_v<Graph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_ve<Graph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_w<Graph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_wv<Graph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_wve<Graph>);
|
||||
def("relative_betweenness_centrality",
|
||||
&relative_betweenness_centrality<Graph>);
|
||||
def("central_point_dominance", ¢ral_point_dominance<Graph>);
|
||||
|
||||
// Digraph
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality<Digraph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_v<Digraph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_ve<Digraph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_w<Digraph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_wv<Digraph>);
|
||||
def("brandes_betweenness_centrality",
|
||||
&brandes_betweenness_centrality_wve<Digraph>);
|
||||
def("relative_betweenness_centrality",
|
||||
&relative_betweenness_centrality<Digraph>);
|
||||
def("central_point_dominance", ¢ral_point_dominance<Digraph>);
|
||||
}
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
183
src/python/breadth_first_search.cpp
Normal file
183
src/python/breadth_first_search.cpp
Normal file
@@ -0,0 +1,183 @@
|
||||
#include <boost/graph/breadth_first_search.hpp>
|
||||
#include "graph.hpp"
|
||||
#include "digraph.hpp"
|
||||
#include "queue.hpp"
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
template<typename Graph>
|
||||
class bfs_visitor
|
||||
{
|
||||
public:
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
|
||||
virtual ~bfs_visitor() {}
|
||||
|
||||
virtual void initialize_vertex(vertex_descriptor s, const Graph& g) const {}
|
||||
virtual void discover_vertex(vertex_descriptor u, const Graph& g) const {}
|
||||
virtual void examine_vertex(vertex_descriptor s, const Graph& g) const {}
|
||||
virtual void examine_edge(edge_descriptor e, const Graph& g) const {}
|
||||
virtual void tree_edge(edge_descriptor e, const Graph& g) const {}
|
||||
virtual void non_tree_edge(edge_descriptor e, const Graph& g) const {}
|
||||
virtual void gray_target(edge_descriptor e, const Graph& g) const {}
|
||||
virtual void black_target(edge_descriptor e, const Graph& g) const {}
|
||||
virtual void finish_vertex(vertex_descriptor s, const Graph& g) const {}
|
||||
};
|
||||
|
||||
template<typename Graph>
|
||||
class bfs_visitor_wrap
|
||||
: public bfs_visitor<Graph>,
|
||||
public boost::python::wrapper<bfs_visitor<Graph> >
|
||||
{
|
||||
public:
|
||||
typedef typename bfs_visitor<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename bfs_visitor<Graph>::edge_descriptor edge_descriptor;
|
||||
|
||||
#define BGL_PYTHON_EVENT(Name,Descriptor) \
|
||||
void Name(Descriptor x, const Graph& g) const \
|
||||
{ \
|
||||
if (override f = this->get_override(#Name)) \
|
||||
f(x, boost::cref(g)); \
|
||||
else bfs_visitor<Graph>::Name(x, g); \
|
||||
} \
|
||||
\
|
||||
void default_##Name(Descriptor x, const Graph& g) const \
|
||||
{ this->bfs_visitor<Graph>::Name(x, g); }
|
||||
|
||||
BGL_PYTHON_EVENT(initialize_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(non_tree_edge, edge_descriptor)
|
||||
BGL_PYTHON_EVENT(gray_target, edge_descriptor)
|
||||
BGL_PYTHON_EVENT(black_target, edge_descriptor)
|
||||
BGL_PYTHON_EVENT(finish_vertex, vertex_descriptor)
|
||||
|
||||
#undef BGL_PYTHON_EVENT
|
||||
};
|
||||
|
||||
template<typename Graph>
|
||||
struct wrap_bfs_visitor_ref
|
||||
{
|
||||
typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
|
||||
typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
|
||||
|
||||
wrap_bfs_visitor_ref(const bfs_visitor<Graph>& v) : v(v) { }
|
||||
|
||||
void initialize_vertex(vertex_descriptor s, const Graph& g) const
|
||||
{ v.initialize_vertex(s, g); }
|
||||
|
||||
void discover_vertex(vertex_descriptor u, const Graph& g) const
|
||||
{ v.discover_vertex(u, g); }
|
||||
|
||||
void examine_vertex(vertex_descriptor u, const Graph& g) const
|
||||
{ v.examine_vertex(u, g); }
|
||||
|
||||
void examine_edge(edge_descriptor e, const Graph& g) const
|
||||
{ v.examine_edge(e, g); }
|
||||
|
||||
void tree_edge(edge_descriptor e, const Graph& g) const
|
||||
{ v.tree_edge(e, g); }
|
||||
|
||||
void non_tree_edge(edge_descriptor e, const Graph& g) const
|
||||
{ v.non_tree_edge(e, g); }
|
||||
|
||||
void gray_target(edge_descriptor e, const Graph& g) const
|
||||
{ v.gray_target(e, g); }
|
||||
|
||||
void black_target(edge_descriptor e, const Graph& g) const
|
||||
{ v.black_target(e, g); }
|
||||
|
||||
void finish_vertex(vertex_descriptor u, const Graph& g) const
|
||||
{ v.finish_vertex(u, g); }
|
||||
|
||||
private:
|
||||
const bfs_visitor<Graph>& v;
|
||||
};
|
||||
|
||||
template<typename Graph>
|
||||
class default_bfs_visitor : public bfs_visitor<Graph> {};
|
||||
|
||||
template<typename Graph>
|
||||
void
|
||||
breadth_first_search_v
|
||||
(const Graph& g,
|
||||
typename Graph::Vertex s,
|
||||
const bfs_visitor<Graph>& visitor)
|
||||
{
|
||||
if (dynamic_cast<const default_bfs_visitor<Graph>*>(&visitor)) {
|
||||
// No visitor. Do default BFS
|
||||
boost::breadth_first_search(g, s,
|
||||
vertex_index_map(g.get_vertex_index_map()));
|
||||
} else {
|
||||
boost::breadth_first_search
|
||||
(g, s,
|
||||
vertex_index_map(g.get_vertex_index_map()).
|
||||
visitor(wrap_bfs_visitor_ref<Graph>(visitor)));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void
|
||||
breadth_first_search_qv
|
||||
(const Graph& g,
|
||||
typename Graph::Vertex s,
|
||||
const python_queue<typename Graph::Vertex>& Q)
|
||||
// const bfs_visitor<Graph>& visitor)
|
||||
{
|
||||
boost::breadth_first_search(g, s,
|
||||
vertex_index_map(g.get_vertex_index_map()));
|
||||
}
|
||||
|
||||
|
||||
void export_breadth_first_search()
|
||||
{
|
||||
using boost::python::arg;
|
||||
|
||||
// Breadth-first search algorithm
|
||||
def("breadth_first_search", &breadth_first_search_v<Graph>,
|
||||
(arg("graph"), "root_vertex",
|
||||
arg("visitor") = default_bfs_visitor<Graph>()));
|
||||
|
||||
def("breadth_first_search2", &breadth_first_search_qv<Graph>);
|
||||
// (arg("graph"), "root_vertex",
|
||||
// arg("buffer") = python_queue<Graph::Vertex>::default_queue()));
|
||||
}
|
||||
|
||||
template<typename Graph>
|
||||
void export_breadth_first_search_in_graph()
|
||||
{
|
||||
using boost::python::arg;
|
||||
|
||||
// BFS visitor
|
||||
class_<bfs_visitor_wrap<Graph>, boost::noncopyable>("BFSVisitor")
|
||||
.def("initialize_vertex", &bfs_visitor<Graph>::initialize_vertex,
|
||||
&bfs_visitor_wrap<Graph>::default_initialize_vertex)
|
||||
.def("examine_vertex", &bfs_visitor<Graph>::examine_vertex,
|
||||
&bfs_visitor_wrap<Graph>::default_examine_vertex)
|
||||
.def("examine_edge", &bfs_visitor<Graph>::examine_edge,
|
||||
&bfs_visitor_wrap<Graph>::default_examine_edge)
|
||||
.def("tree_edge", &bfs_visitor<Graph>::tree_edge,
|
||||
&bfs_visitor_wrap<Graph>::default_tree_edge)
|
||||
.def("non_tree_edge", &bfs_visitor<Graph>::non_tree_edge,
|
||||
&bfs_visitor_wrap<Graph>::default_non_tree_edge)
|
||||
.def("gray_target", &bfs_visitor<Graph>::gray_target,
|
||||
&bfs_visitor_wrap<Graph>::default_gray_target)
|
||||
.def("black_target", &bfs_visitor<Graph>::black_target,
|
||||
&bfs_visitor_wrap<Graph>::default_black_target)
|
||||
.def("finish_vertex", &bfs_visitor<Graph>::finish_vertex,
|
||||
&bfs_visitor_wrap<Graph>::default_finish_vertex)
|
||||
;
|
||||
|
||||
class_<default_bfs_visitor<Graph>, bases<bfs_visitor<Graph> > >
|
||||
("DefaultBFSVisitor", no_init);
|
||||
|
||||
python_queue<typename Graph::Vertex>::declare("VertexQueue",
|
||||
"DefaultVertexQueue");
|
||||
}
|
||||
|
||||
template void export_breadth_first_search_in_graph<Graph>();
|
||||
template void export_breadth_first_search_in_graph<Digraph>();
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
10
src/python/digraph.cpp
Normal file
10
src/python/digraph.cpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#include "digraph.hpp"
|
||||
#include "basic_graph.cpp"
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
void export_Digraph()
|
||||
{
|
||||
export_basic_graph<bidirectionalS>("Digraph");
|
||||
}
|
||||
} } } // end namespace boost::graph::python
|
||||
10
src/python/digraph.hpp
Normal file
10
src/python/digraph.hpp
Normal file
@@ -0,0 +1,10 @@
|
||||
#ifndef BOOST_GRAPH_PYTHON_DIGRAPH_HPP
|
||||
#define BOOST_GRAPH_PYTHON_DIGRAPH_HPP
|
||||
|
||||
#include "basic_graph.hpp"
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
typedef basic_graph<bidirectionalS> Digraph;
|
||||
} } } // end namespace boost::graph::python
|
||||
|
||||
#endif // BOOST_GRAPH_PYTHON_DIGRAPH_HPP
|
||||
24
src/python/done.cpp
Normal file
24
src/python/done.cpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#include "done.hpp"
|
||||
#include <boost/python.hpp>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
using namespace boost::python;
|
||||
|
||||
class done_wrap : public done, public wrapper<done>
|
||||
{
|
||||
public:
|
||||
bool operator()() const
|
||||
{
|
||||
return this->get_override("__call__")();
|
||||
}
|
||||
};
|
||||
|
||||
void export_done()
|
||||
{
|
||||
class_<done_wrap, boost::noncopyable>("Done")
|
||||
.def("__call__", pure_virtual(&done::operator()))
|
||||
;
|
||||
}
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
15
src/python/done.hpp
Normal file
15
src/python/done.hpp
Normal file
@@ -0,0 +1,15 @@
|
||||
#ifndef BOOST_GRAPH_PYTHON_DONE_HPP
|
||||
#define BOOST_GRAPH_PYTHON_DONE_HPP
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
class done
|
||||
{
|
||||
public:
|
||||
virtual ~done() { }
|
||||
virtual bool operator()() const = 0;
|
||||
};
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
|
||||
#endif // BOOST_GRAPH_PYTHON_DONE_HPP
|
||||
11
src/python/graph.cpp
Normal file
11
src/python/graph.cpp
Normal file
@@ -0,0 +1,11 @@
|
||||
#include "graph.hpp"
|
||||
#include "basic_graph.cpp"
|
||||
#include <iostream>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
void export_Graph()
|
||||
{
|
||||
export_basic_graph<undirectedS>("Graph");
|
||||
}
|
||||
} } } // end namespace boost::graph::python
|
||||
28
src/python/graph.hpp
Normal file
28
src/python/graph.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef BOOST_GRAPH_PYTHON_GRAPH_HPP
|
||||
#define BOOST_GRAPH_PYTHON_GRAPH_HPP
|
||||
|
||||
#include "basic_graph.hpp"
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
typedef basic_graph<undirectedS> Graph;
|
||||
|
||||
#if 0
|
||||
class Graph : public basic_graph<undirectedS>
|
||||
{
|
||||
typedef basic_graph<undirectedS> inherited;
|
||||
|
||||
public:
|
||||
Graph() : inherited() { }
|
||||
Graph(const std::string& filename, graph_file_kind kind)
|
||||
: inherited(filename, kind) { }
|
||||
|
||||
vertex_iterator vertices_begin() const;
|
||||
vertex_iterator vertices_end() const;
|
||||
edge_iterator edges_begin() const;
|
||||
edge_iterator edges_end() const;
|
||||
};
|
||||
#endif
|
||||
} } } // end namespace boost::graph::python
|
||||
|
||||
#endif // BOOST_GRAPH_PYTHON_GRAPH_HPP
|
||||
45
src/python/graphviz.cpp
Normal file
45
src/python/graphviz.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "basic_graph.hpp"
|
||||
#include <boost/graph/graphviz.hpp>
|
||||
#include <fstream>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
template<typename DirectedS>
|
||||
void
|
||||
basic_graph<DirectedS>::read_graphviz(const std::string& filename,
|
||||
const std::string& node_id)
|
||||
{
|
||||
std::ifstream in(filename.c_str());
|
||||
boost::read_graphviz(in, *this, dp, node_id);
|
||||
}
|
||||
|
||||
template<typename DirectedS>
|
||||
void
|
||||
basic_graph<DirectedS>::write_graphviz(const std::string& filename,
|
||||
const std::string& node_id)
|
||||
{
|
||||
std::ofstream out(filename.c_str());
|
||||
boost::write_graphviz(out, *this, dp, node_id,
|
||||
get_vertex_map<std::string>("node_id"));
|
||||
}
|
||||
|
||||
// Explicit instantiations
|
||||
template
|
||||
void
|
||||
basic_graph<undirectedS>::read_graphviz(const std::string& filename,
|
||||
const std::string& node_id);
|
||||
template
|
||||
void
|
||||
basic_graph<undirectedS>::write_graphviz(const std::string& filename,
|
||||
const std::string& node_id);
|
||||
|
||||
template
|
||||
void
|
||||
basic_graph<bidirectionalS>::read_graphviz(const std::string& filename,
|
||||
const std::string& node_id);
|
||||
template
|
||||
void
|
||||
basic_graph<bidirectionalS>::write_graphviz(const std::string& filename,
|
||||
const std::string& node_id);
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
40
src/python/module.cpp
Normal file
40
src/python/module.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "basic_graph.cpp"
|
||||
#include "graph.hpp"
|
||||
#include "digraph.hpp"
|
||||
#include <boost/python.hpp>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
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();
|
||||
template<typename Graph> void export_breadth_first_search_in_graph();
|
||||
|
||||
template<typename Graph>
|
||||
void export_in_graph()
|
||||
{
|
||||
export_breadth_first_search_in_graph<Graph>();
|
||||
}
|
||||
|
||||
BOOST_PYTHON_MODULE(bgl)
|
||||
{
|
||||
enum_<graph_file_kind>("file_kind")
|
||||
.value("adjlist", gfk_adjlist)
|
||||
.value("graphviz", gfk_graphviz)
|
||||
;
|
||||
|
||||
export_Graph();
|
||||
export_Digraph();
|
||||
export_betweenness_centrality();
|
||||
export_page_rank();
|
||||
export_done();
|
||||
export_breadth_first_search();
|
||||
}
|
||||
|
||||
template void export_in_graph<Graph>();
|
||||
template void export_in_graph<Digraph>();
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
58
src/python/queue.hpp
Normal file
58
src/python/queue.hpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#ifndef BOOST_GRAPH_PYTHON_QUEUE_HPP
|
||||
#define BOOST_GRAPH_PYTHON_QUEUE_HPP
|
||||
|
||||
#include <boost/python.hpp>
|
||||
|
||||
namespace boost { namespace graph { namespace python {
|
||||
|
||||
template<typename T>
|
||||
class python_queue
|
||||
{
|
||||
class wrap
|
||||
: public python_queue<T>, public boost::python::wrapper<python_queue<T> >
|
||||
{
|
||||
public:
|
||||
bool empty() const { return this->get_override("empty")(); }
|
||||
T top() const { return this->get_override("top")(); }
|
||||
void pop() { this->get_override("pop")(); }
|
||||
void push(const T& x) { this->get_override("push")(x); }
|
||||
};
|
||||
|
||||
public:
|
||||
class default_queue : public python_queue<T>
|
||||
{
|
||||
bool empty() const { return true; }
|
||||
T top() const { return T(); }
|
||||
void pop() {}
|
||||
void push(const T&) {}
|
||||
};
|
||||
|
||||
virtual ~python_queue() {}
|
||||
virtual bool empty() const = 0;
|
||||
virtual T top() const = 0;
|
||||
virtual void pop() = 0;
|
||||
virtual void push(const T&) = 0;
|
||||
|
||||
static void declare(const char* name, const char* default_name)
|
||||
{
|
||||
using namespace boost::python;
|
||||
|
||||
// if (objects::registered_class_object(type_id<wrap>()).get() == 0) {
|
||||
class_<wrap, boost::noncopyable>(name)
|
||||
.def("empty", pure_virtual(&python_queue<T>::empty))
|
||||
.def("top", pure_virtual(&python_queue<T>::top))
|
||||
.def("pop", pure_virtual(&python_queue<T>::pop))
|
||||
.def("push", pure_virtual(&python_queue<T>::push))
|
||||
;
|
||||
// }
|
||||
|
||||
// if (objects::registered_class_object(type_id<default_queue>()).get() == 0)
|
||||
{
|
||||
class_<default_queue, bases<python_queue<T> > >(default_name, no_init);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} } } // end namespace boost::graph::python
|
||||
|
||||
#endif // BOOST_GRAPH_PYTHON_QUEUE_HPP
|
||||
Reference in New Issue
Block a user