2
0
mirror of https://github.com/boostorg/graph.git synced 2026-01-31 08: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