2
0
mirror of https://github.com/boostorg/graph.git synced 2026-01-28 19:22:11 +00:00

Pickle support

[SVN r29735]
This commit is contained in:
Douglas Gregor
2005-06-22 14:58:25 +00:00
parent 9934fd8da4
commit f11331b2f1
5 changed files with 265 additions and 66 deletions

View File

@@ -42,64 +42,6 @@ inline std::istream& operator>>(std::istream& in, default_color_type& c)
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,
typename ValueType = typename property_traits<PropertyMap>::value_type>
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 PropertyMap>
class copying_dynamic_adaptor<PropertyMap, boost::python::object>
: 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)));
}
virtual std::string get_string(const any& key)
{
using boost::python::extract;
using boost::python::str;
return std::string(
extract<const char*>(str(boost::get(this->base(),
any_cast<key_type>(key)))));
}
};
template<typename DirectedS>
struct build_string_property_maps
{
@@ -117,13 +59,13 @@ struct build_string_property_maps
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;
typedef python_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;
typedef python_dynamic_adaptor<property_map_type> adaptor_type;
result.reset
(new adaptor_type(property_map_type(g->num_edges(),
g->get_edge_index_map())));
@@ -319,7 +261,7 @@ 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;
typedef python_dynamic_adaptor<result_type> adaptor_type;
dynamic_properties::iterator i = dp.lower_bound(name);
while (i != dp.end() && i->first == name) {
@@ -348,7 +290,7 @@ basic_graph<DirectedS>::get_vertex_map(const std::string& name)
}
typedef vector_property_map<T, VertexIndexMap> property_map_type;
typedef copying_dynamic_adaptor<property_map_type> adaptor_type;
typedef python_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)));
@@ -376,7 +318,7 @@ 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;
typedef python_dynamic_adaptor<result_type> adaptor_type;
dynamic_properties::iterator i = dp.lower_bound(name);
while (i != dp.end() && i->first == name) {
@@ -404,7 +346,7 @@ basic_graph<DirectedS>::get_edge_map(const std::string& name)
}
typedef vector_property_map<T, EdgeIndexMap> property_map_type;
typedef copying_dynamic_adaptor<property_map_type> adaptor_type;
typedef python_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)));
@@ -453,7 +395,7 @@ void basic_graph<DirectedS>::remove_vertex(Vertex 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).
dynamic_cast<python_dynamic_property_map&>(*i->second).
copy_value(vertex, Vertex(index_to_vertex.back()));
}
}
@@ -519,7 +461,7 @@ void basic_graph<DirectedS>::remove_edge(Edge 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).
dynamic_cast<python_dynamic_property_map&>(*i->second).
copy_value(edge, Edge(index_to_edge.back()));
}
}
@@ -663,6 +605,8 @@ void export_basic_graph(const char* name)
.def("read_graphviz", &Graph::read_graphviz)
.def("write_graphviz", &Graph::write_graphviz)
.def("write_graphviz", &Graph::write_graphviz_def)
// Pickling
.def_pickle(graph_pickle_suite<DirectedS>())
);
export_in_graph<Graph>();

View File

@@ -350,6 +350,9 @@ class basic_graph
inherited& base() { return *this; }
const inherited& base() const { return *this; }
dynamic_properties& get_dynamic_properties() { return dp; }
const dynamic_properties& get_dynamic_properties() const { return dp; }
protected:
void renumber_vertices();
void renumber_edges();
@@ -456,6 +459,103 @@ typename basic_graph<DirectedS>::EdgeIndexMap
get(edge_index_t, const basic_graph<DirectedS>& g)
{ return g.get_edge_index_map(); }
template<typename DirectedS>
struct graph_pickle_suite : boost::python::pickle_suite
{
typedef basic_graph<DirectedS> Graph;
typedef typename Graph::vertex_descriptor Vertex;
typedef typename Graph::edge_descriptor Edge;
static
boost::python::tuple
getstate(boost::python::object g_obj);
static
void
setstate(boost::python::object g_obj, boost::python::tuple state);
};
class python_dynamic_property_map
{
public:
virtual ~python_dynamic_property_map() {}
virtual void copy_value(const any& to, const any& from) = 0;
virtual boost::python::object get_python(const any& key) = 0;
};
template<typename PropertyMap,
typename ValueType = typename property_traits<PropertyMap>::value_type>
class python_dynamic_adaptor
: public boost::detail::dynamic_property_map_adaptor<PropertyMap>,
public python_dynamic_property_map
{
typedef boost::detail::dynamic_property_map_adaptor<PropertyMap> inherited;
public:
typedef typename property_traits<PropertyMap>::key_type key_type;
explicit python_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)));
}
virtual boost::python::object get_python(const any& key)
{
#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
return boost::get(this->base(), any_cast<key_type>(key));
#else
using boost::get;
return boost::python::object(get(this->base(), any_cast<key_type>(key)));
#endif
}
};
template<typename PropertyMap>
class python_dynamic_adaptor<PropertyMap, boost::python::object>
: public boost::detail::dynamic_property_map_adaptor<PropertyMap>,
public python_dynamic_property_map
{
typedef boost::detail::dynamic_property_map_adaptor<PropertyMap> inherited;
public:
typedef typename property_traits<PropertyMap>::key_type key_type;
explicit python_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)));
}
virtual std::string get_string(const any& key)
{
using boost::python::extract;
using boost::python::str;
return std::string(
extract<const char*>(str(boost::get(this->base(),
any_cast<key_type>(key)))));
}
virtual boost::python::object get_python(const any& key)
{
#if defined(__GNUC__) && (__GNUC__ == 2) && (__GNUC_MINOR__ == 95)
return boost::get(this->base(), any_cast<key_type>(key));
#else
using boost::get;
return get(this->base(), any_cast<key_type>(key));
#endif
}
};
} } } // end namespace boost::graph::python
#if 0

150
src/python/pickle.cpp Normal file
View File

@@ -0,0 +1,150 @@
// Copyright 2005 The Trustees of Indiana University.
// Use, modification and distribution is subject to the Boost Software
// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
// Authors: Douglas Gregor
// Andrew Lumsdaine
#include "graph.hpp"
#include "digraph.hpp"
#include <boost/graph/iteration_macros.hpp>
namespace boost { namespace graph { namespace python {
template<typename DirectedS>
boost::python::tuple
graph_pickle_suite<DirectedS>::getstate(boost::python::object g_obj)
{
using namespace boost::python;
using boost::python::tuple;
using boost::python::make_tuple;
using boost::python::list;
const Graph& g = extract<const Graph&>(g_obj)();
typename Graph::VertexIndexMap vertex_index_map = g.get_vertex_index_map();
typename Graph::EdgeIndexMap edge_index_map = g.get_edge_index_map();
dict vertex_properties;
dict edge_properties;
// Collect edges
std::vector<tuple> the_edges(g.num_edges());
BGL_FORALL_EDGES_T(e, g, Graph)
the_edges[get(edge_index_map, e)] =
make_tuple(get(vertex_index_map, source(e, g)),
get(vertex_index_map, target(e, g)));
list edges_list;
for (std::vector<tuple>::iterator i = the_edges.begin();
i != the_edges.end(); ++i)
edges_list.append(*i);
// Collect vertex and edge properties
const dynamic_properties& dp = g.get_dynamic_properties();
for (dynamic_properties::const_iterator pm = dp.begin();
pm != dp.end(); ++pm) {
python_dynamic_property_map* pmap =
dynamic_cast<python_dynamic_property_map*>(pm->second);
if (pm->second->key() == typeid(Vertex)) {
std::vector<object> values(g.num_vertices());
BGL_FORALL_VERTICES_T(v, g, Graph)
values[get(vertex_index_map, v)] = pmap->get_python(v);
list values_list;
for (std::vector<object>::iterator i = values.begin();
i != values.end(); ++i)
values_list.append(*i);
vertex_properties[pm->first] = tuple(values_list);
} else if (pm->second->key() == typeid(Edge)) {
std::vector<object> values(g.num_edges());
BGL_FORALL_EDGES_T(e, g, Graph)
values[get(edge_index_map, e)] = pmap->get_python(e);
list values_list;
for (std::vector<object>::iterator i = values.begin();
i != values.end(); ++i)
values_list.append(*i);
edge_properties[pm->first] = tuple(values_list);
} else {
assert(false);
}
}
return make_tuple(g_obj.attr("__dict__"),
g.num_vertices(),
edges_list,
vertex_properties,
edge_properties);
}
template<typename DirectedS>
void
graph_pickle_suite<DirectedS>::setstate(boost::python::object g_obj,
boost::python::tuple state)
{
using namespace boost::python;
using boost::python::tuple;
using boost::python::make_tuple;
using boost::python::list;
Graph& g = extract<Graph&>(g_obj)();
// restore the graph's __dict__
dict d = extract<dict>(g_obj.attr("__dict__"))();
d.update(state[0]);
// Get the number of vertices
typedef typename graph_traits<Graph>::vertices_size_type vertices_size_type;
vertices_size_type n = extract<vertices_size_type>(state[1]);
std::vector<Vertex> vertices;
vertices.reserve(n);
while (vertices.size() < n) vertices.push_back(g.add_vertex());
// Get the edges
typedef typename graph_traits<Graph>::edges_size_type edges_size_type;
std::vector<Edge> the_edges;
list edges_list = extract<list>(state[2]);
edges_size_type m = extract<int>(edges_list.attr("__len__")());
the_edges.reserve(m);
for (unsigned i = 0; i < m; ++i) {
tuple e = extract<tuple>(edges_list[i]);
the_edges.push_back
(g.add_edge(vertices[extract<vertices_size_type>(e[0])],
vertices[extract<vertices_size_type>(e[1])]));
}
// Get the vertex properties
typedef typename Graph::VertexIndexMap VertexIndexMap;
dict vertex_properties = extract<dict>(state[3]);
list vertex_map_names = vertex_properties.keys();
while (vertex_map_names != list()) {
object name_obj = vertex_map_names.pop(0);
const char* name = extract<const char*>(name_obj);
vector_property_map<object, VertexIndexMap> pmap =
g.get_vertex_object_map(name);
tuple values = extract<tuple>(vertex_properties[name_obj]);
for (vertices_size_type i = 0; i < g.num_vertices(); ++i)
put(pmap, vertices[i], values[i]);
}
// Get the edge properties
typedef typename Graph::EdgeIndexMap EdgeIndexMap;
dict edge_properties = extract<dict>(state[4]);
list edge_map_names = edge_properties.keys();
while (edge_map_names != list()) {
object name_obj = edge_map_names.pop(0);
const char* name = extract<const char*>(name_obj);
vector_property_map<object, EdgeIndexMap> pmap =
g.get_edge_object_map(name);
tuple values = extract<tuple>(edge_properties[name_obj]);
for (edges_size_type i = 0; i < g.num_edges(); ++i)
put(pmap, the_edges[i], values[i]);
}
}
template struct graph_pickle_suite<undirectedS>;
template struct graph_pickle_suite<bidirectionalS>;
} } } // end namespace boost::graph::python