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:
@@ -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>();
|
||||
|
||||
@@ -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
150
src/python/pickle.cpp
Normal 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
|
||||
|
||||
Reference in New Issue
Block a user