diff --git a/src/graph/graph.hh b/src/graph/graph.hh index ef632f4b22123dc98bb19cbabe101b77372950b3..303a33d93457d2d5f70c7d4d6088224f1ec8770f 100644 --- a/src/graph/graph.hh +++ b/src/graph/graph.hh @@ -116,6 +116,8 @@ public: python::object AddEdge(const python::object& s, const python::object& t); void RemoveEdge(const python::object& e); + python::object DegreeMap(string deg) const; + // used for graph properties graph_property_tag GetDescriptor() const { return graph_property_tag(); } bool CheckValid() const {return true;} diff --git a/src/graph/graph_bind.cc b/src/graph/graph_bind.cc index 1f05c64f99bb51aeac0a30b44b9d0330f4590f88..6b55198f79590f3448b35b83cfff207796f57978 100644 --- a/src/graph/graph_bind.cc +++ b/src/graph/graph_bind.cc @@ -314,6 +314,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_core) .def("AddEdge", &GraphInterface::AddEdge) .def("RemoveVertex", &GraphInterface::RemoveVertex) .def("RemoveEdge", &GraphInterface::RemoveEdge) + .def("DegreeMap", &GraphInterface::DegreeMap) .def("Clear", &GraphInterface::Clear) .def("ClearEdges", &GraphInterface::ClearEdges) .def("GetVertexIndex", &GraphInterface::GetVertexIndex) diff --git a/src/graph/graph_python_interface.cc b/src/graph/graph_python_interface.cc index 6af3f4319b23c66f4c7c7517107858d7e62d52c2..189a43866286fb05c6392a15706238dca0e3a40e 100644 --- a/src/graph/graph_python_interface.cc +++ b/src/graph/graph_python_interface.cc @@ -228,6 +228,48 @@ void GraphInterface::RemoveEdge(const python::object& e) remove_edge(de, _mg); } +struct get_degree_map +{ + template + void operator()(const Graph* gp, DegreeMap deg_map, DegS deg) const + { + const Graph& g = *gp; + int i, N = num_vertices(g); + #pragma omp parallel for default(shared) private(i) schedule(dynamic) + for (i = 0; i < N; ++i) + { + typename graph_traits::vertex_descriptor v = vertex(i, g); + if (v == graph_traits::null_vertex()) + continue; + deg_map[v] = deg(v, g); + } + } +}; + +python::object GraphInterface::DegreeMap(string deg) const +{ + typedef property_map_type::apply::type + map_t; + + map_t deg_map(_vertex_index); + deg_map.reserve(num_vertices(_mg)); + + if (deg == "in") + run_action<>()(*this, + lambda::bind(get_degree_map(), lambda::_1, + deg_map, in_degreeS()))(); + else if (deg == "out") + run_action<>()(*this, + lambda::bind(get_degree_map(), lambda::_1, + deg_map, out_degreeS()))(); + else if (deg == "total") + run_action<>()(*this, + lambda::bind(get_degree_map(), lambda::_1, + deg_map, total_degreeS()))(); + return python::object(PythonPropertyMap(deg_map)); +} + // // Below are the functions with will properly register all the types to python, // for every filter, type, etc. diff --git a/src/graph_tool/core.py b/src/graph_tool/core.py index 93c00044761575c2798d8ef5c243f85be8c471a6..c8fefa35127f7cf361ad31cf9ddc87b6977b7804 100644 --- a/src/graph_tool/core.py +++ b/src/graph_tool/core.py @@ -532,6 +532,15 @@ class Graph(object): if g != self: g.pop_filter() + # degree property map + @_handle_exceptions + @_limit_args({"deg":["in","out","total"]}) + def degree_property_map(self, deg): + """Create and return a vertex property map containing the degree type + given by `deg`""" + return PropertyMap(self.__graph.DegreeMap(deg), self, "v") + + # I/O operations # ==============