// graph-tool -- a general graph modification and manipulation thingy // // Copyright (C) 2006 Tiago de Paula Peixoto // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #ifndef PYTHON_FILTERING_HH #define PYTHON_FILTERING_HH #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace graph_tool { using namespace boost; //============================================================================== // populate_python_funcs //============================================================================== template > struct populate_python_funcs { template void operator()(const Graph& g, Descriptor& u, const dynamic_properties& dp, python::object& variables) { for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter) { if (iter->second->key() == typeid(Descriptor)) variables[iter->first] = python::make_function(get_value(*iter->second, u), python::default_call_policies(), mpl::vector::type()); } populate_specific(g, u, dp, variables); } typedef mpl::vector degrees; template void populate_specific(const Graph& g, typename graph_traits::vertex_descriptor& v, const dynamic_properties& dp, python::object& variables) { mpl::for_each(put_degree_function(g, v, variables)); typedef typename mpl::if_ >::type base_degrees; mpl::for_each(put_base_degree_function(g, v, variables, "orig_")); } template void populate_specific(const Graph& g, typename graph_traits::edge_descriptor& e, const dynamic_properties& dp, python::object& variables) { typedef typename graph_traits::vertex_descriptor vertex_descriptor; variables["is_loop"] = python::make_function(is_loop(g, e), python::default_call_policies(), mpl::vector::type()); for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter) { if (iter->second->key() == typeid(vertex_descriptor)) { variables["source_"+iter->first] = python::make_function(get_source_or_target_value(g, *iter->second, e), python::default_call_policies(), mpl::vector::type()); variables["target_"+iter->first] = python::make_function(get_source_or_target_value(g, *iter->second, e), python::default_call_policies(), mpl::vector::type()); } } mpl::for_each(put_source_or_target_degree_function(g, e, variables, "source_")); mpl::for_each(put_source_or_target_degree_function(g, e, variables, "target_")); } template struct get_value { get_value(const dynamic_property_map& dmap, const VertexOrEdge& e) : _dmap(dmap), _e(e) {} struct try_conversion { try_conversion(get_value& parent): _parent(parent) {} template void operator()(Type) { any any_val = const_cast(_parent._dmap).get(_parent._e); Type* value = any_cast(&any_val); if (value != 0) _parent._retval = python::object(*value); } get_value& _parent; }; python::object operator()() { typedef mpl::vector value_types; mpl::for_each(try_conversion(*this)); return _retval; } const dynamic_property_map& _dmap; const VertexOrEdge& _e; python::object _retval; }; template struct get_source_or_target_value { typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; get_source_or_target_value(const Graph& g, dynamic_property_map& dmap, const edge_descriptor& e) : _g(g),_dmap(dmap),_e(e){} python::object operator()() { vertex_descriptor _s; if (Source) _s = source(_e, _g); else _s = target(_e, _g); get_value get_value(_dmap, _s); return get_value(); } const Graph& _g; const dynamic_property_map& _dmap; const edge_descriptor& _e; }; template struct get_degree { typedef typename graph_traits::vertex_descriptor vertex_descriptor; get_degree(const Graph& g, const vertex_descriptor& v) : _g(g), _v(v) {} python::object operator()() { return python::object(_degree(_v, _g)); } const Graph& _g; const vertex_descriptor& _v; Degree _degree; }; template struct put_degree_function { typedef typename graph_traits::vertex_descriptor vertex_descriptor; put_degree_function(const Graph& g, const vertex_descriptor& v, python::object variables, std::string prefix = "") : _g(g), _v(v), _variables(variables), _prefix(prefix) {} template void operator()(Degree degree) { _variables[_prefix+degree.name()] = python::make_function(get_degree(_g, _v), python::default_call_policies(), mpl::vector::type()); } const Graph& _g; const vertex_descriptor& _v; python::object& _variables; std::string _prefix; }; template struct put_base_degree_function: public put_degree_function { typedef typename graph_traits::vertex_descriptor vertex_descriptor; put_base_degree_function(const Graph& g, const vertex_descriptor& v, python::object& variables, std::string prefix = "") : put_degree_function(g, v, variables, prefix) {} template void operator()(Degree degree) { this->_variables[this->_prefix+degree.name()] = python::make_function(get_degree(this->_g.m_g, this->_v), python::default_call_policies(), mpl::vector::type()); } }; template struct put_source_or_target_degree_function { typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; put_source_or_target_degree_function(const Graph& g, const edge_descriptor& e, python::object& variables, std::string prefix = "") : _g(g), _e(e), _variables(variables), _prefix(prefix) {} template void operator()(Degree d) { vertex_descriptor v; if (Source) v = source(_e, this->_g); else v = target(_e, this->_g); put_degree_function(_g, v, _variables, _prefix)(d); } const Graph& _g; const edge_descriptor& _e; python::object& _variables; std::string _prefix; }; template struct is_loop { typedef typename graph_traits::edge_descriptor edge_descriptor; is_loop(const Graph& g, const edge_descriptor& e): _g(g), _e(e) {} python::object operator()() { return python::object(source(_e, _g) == target(_e, _g)); } const Graph& _g; const edge_descriptor& _e; }; }; //============================================================================== // PythonFilter //============================================================================== template > class PythonFilter { public: typedef typename graph_traits::vertex_descriptor vertex_descriptor; typedef typename graph_traits::edge_descriptor edge_descriptor; typedef mpl::vector degrees; PythonFilter(){} PythonFilter(const Graph& g, const dynamic_properties& dp, python::object filter) : _g(&g), _filter(filter[0]) { python::object variables = filter[1]; populate_python_funcs()(*_g, _u, dp, variables); } inline bool operator() (Descriptor u) const { _u = u; return python::extract(_filter()); } private: Graph const* _g; python::object _filter; static Descriptor _u; }; template Descriptor PythonFilter::_u; } //graph_tool namespace #endif