2
0
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:
Douglas Gregor
2005-03-03 14:06:42 +00:00
parent e88397d209
commit 6bf503fa56
13 changed files with 1441 additions and 0 deletions

538
src/python/basic_graph.cpp Normal file
View 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
View 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

View 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", &central_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", &central_point_dominance<Digraph>);
}
} } } // end namespace boost::graph::python

View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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
View 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