diff --git a/src/boost-workaround/boost/vector_property_map.hpp b/src/boost-workaround/boost/vector_property_map.hpp new file mode 100644 index 0000000000000000000000000000000000000000..afc1e1b23b5d0486c0642148de250da4f4e5c3b4 --- /dev/null +++ b/src/boost-workaround/boost/vector_property_map.hpp @@ -0,0 +1,100 @@ +// Copyright (C) Vladimir Prus 2003. +// Distributed under 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) +// +// See http://www.boost.org/libs/graph/vector_property_map.html for +// documentation. +// + +#ifndef VECTOR_PROPERTY_MAP_HPP_VP_2003_03_04 +#define VECTOR_PROPERTY_MAP_HPP_VP_2003_03_04 + +#include +#include +#include + +namespace boost { + template + class vector_property_map + : public boost::put_get_helper< + typename std::iterator_traits< + typename std::vector::iterator >::reference, + vector_property_map > + { + public: + typedef typename property_traits::key_type key_type; + typedef T value_type; + typedef typename std::iterator_traits< + typename std::vector::iterator >::reference reference; + typedef boost::lvalue_property_map_tag category; + + vector_property_map(const IndexMap& index = IndexMap()) + : store(new std::vector()), index(index) + {} + + vector_property_map(unsigned initial_size, + const IndexMap& index = IndexMap()) + : store(new std::vector(initial_size)), index(index) + {} + + typename std::vector::iterator storage_begin() + { + return store->begin(); + } + + typename std::vector::iterator storage_end() + { + return store->end(); + } + + typename std::vector::const_iterator storage_begin() const + { + return store->begin(); + } + + typename std::vector::const_iterator storage_end() const + { + return store->end(); + } + + void reserve(size_t size) + { + if (store->size() < size) + store->resize(size); + } + + std::vector& get_storage() { return (*store); } + + public: + // Copy ctor absent, default semantics is OK. + // Assignment operator absent, default semantics is OK. + // CONSIDER: not sure that assignment to 'index' is correct. + + reference operator[](const key_type& v) const { + typename property_traits::value_type i = get(index, v); + if (static_cast(i) >= store->size()) { + store->resize(i + 1, T()); + } + return (*store)[i]; + } + private: + // Conceptually, we have a vector of infinite size. For practical + // purposes, we start with an empty vector and grow it as needed. + // Note that we cannot store pointer to vector here -- we cannot + // store pointer to data, because if copy of property map resizes + // the vector, the pointer to data will be invalidated. + // I wonder if class 'pmap_ref' is simply needed. + shared_ptr< std::vector > store; + IndexMap index; + }; + + template + vector_property_map + make_vector_property_map(IndexMap index) + { + return vector_property_map(index); + } +} + +#endif diff --git a/src/graph/graph_bind.cc b/src/graph/graph_bind.cc index f1499ece42898595a3045c5aefcfb872ad7acb94..1f05c64f99bb51aeac0a30b44b9d0330f4590f88 100644 --- a/src/graph/graph_bind.cc +++ b/src/graph/graph_bind.cc @@ -16,9 +16,9 @@ // along with this program. If not, see . #include "graph.hh" +#define NUMPY_EXPORT #include "graph_python_interface.hh" #include "graph_util.hh" -#define NUMPY_EXPORT #include "numpy_bind.hh" #include diff --git a/src/graph/graph_python_interface.hh b/src/graph/graph_python_interface.hh index 4f0c73432977527284b33be2e8fca0c90ad9a547..34a048466172a5eb5b41408f092e186b575da75d 100644 --- a/src/graph/graph_python_interface.hh +++ b/src/graph/graph_python_interface.hh @@ -27,6 +27,7 @@ #include "graph.hh" #include "graph_filtering.hh" #include "graph_selectors.hh" +#include "numpy_bind.hh" #include #include @@ -428,6 +429,28 @@ public: (_pmap)); } + python::object GetArray(size_t size) + { + typedef typename mpl::or_< + is_same, + typename mpl::not_::type>::type> + ::type is_vector_map; + return get_array(_pmap, size, is_vector_map()); + } + + python::object get_array(PropertyMap pmap, size_t size, mpl::bool_) + { + _pmap.reserve(size); + return wrap_vector_not_owned(_pmap.get_storage()); + } + + python::object get_array(PropertyMap pmap, size_t size, mpl::bool_) + { + return python::object(); + } + private: PropertyMap _pmap; // hold an internal copy, since it's cheap }; diff --git a/src/graph/graph_python_interface_export.cc b/src/graph/graph_python_interface_export.cc index 4f455b4e1d0111d2179c84424fd24945b0ec1bc1..961bb37b51f9c731182cacd605b3b347374c7d2f 100644 --- a/src/graph/graph_python_interface_export.cc +++ b/src/graph/graph_python_interface_export.cc @@ -66,7 +66,8 @@ struct export_vertex_property_map return_policy()) .def("__setitem__", &pmap_t::template SetValue) .def("get_map", &pmap_t::GetMap) - .def("get_dynamic_map", &pmap_t::GetDynamicMap); + .def("get_dynamic_map", &pmap_t::GetDynamicMap) + .def("get_array", &pmap_t::GetArray); } string _name; diff --git a/src/graph_tool/core.py b/src/graph_tool/core.py index 8658642418fb54c294a41b44357144bf79a29e35..93c00044761575c2798d8ef5c243f85be8c471a6 100644 --- a/src/graph_tool/core.py +++ b/src/graph_tool/core.py @@ -152,6 +152,26 @@ class PropertyMap(object): """The value type of the map""" return self.__map.value_type() + def get_array(self): + """Get an array with property values + + .. WARNING:: + + The returned array does not own the data, which belongs to the + property map. Therefore, the returned array cannot have a longer + lifespan than the property map itself! Futhermore, if the graph + changes, it may leave the pointer to the data in the array dangling! + Do *not* store the array if the graph is to be modified, or the + original property map deleted; *store a copy instead*! + """ + if self.__key_type == 'v': + n = self.__g().num_vertices() + elif self.__key_type == 'e': + n = self.__g().num_edges() + else: + n = 1 + return self.__map.get_array(n) + class PropertyDict(dict): """Wrapper for the dict of vertex, graph or edge properties, which sets the value on the property map when changed in the dict."""