graph_python_filtering.hh 9.18 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006  Tiago de Paula Peixoto <tiago@forked.de>
//
// 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 <boost/graph/graph_traits.hpp>
#include <boost/graph/filtered_graph.hpp>
#include <boost/graph/reverse_graph.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/map.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/logical.hpp>
#include <boost/python/object.hpp>
#include <boost/python/dict.hpp>
#include <boost/python/extract.hpp>
#include <boost/python/make_function.hpp>

namespace graph_tool
{
using namespace boost;

//==============================================================================
42
// populate_python_funcs
43
44
//==============================================================================

45
46
47
48
49
template <class Descriptor, class HasBase = mpl::bool_<false> >
struct populate_python_funcs
{
    template<class Graph>
    void operator()(const Graph& g, Descriptor& u, const dynamic_properties& dp, python::object& variables)
50
51
52
    {
	for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
	{
53
54
	    if (iter->second->key() == typeid(Descriptor))
		variables[iter->first] = python::make_function(get_value<Descriptor>(*iter->second, u), 
55
56
							       python::default_call_policies(), mpl::vector<python::object>::type());
	}
57
58
	populate_specific(g, u, dp, variables);
    }
59

60
    typedef mpl::vector<in_degreeS, out_degreeS, total_degreeS> degrees;
61

62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
    template <class Graph>
    void populate_specific(const Graph& g, typename graph_traits<Graph>::vertex_descriptor& v, const dynamic_properties& dp, python::object& variables)
    {
	mpl::for_each<degrees>(put_degree_function<Graph>(g, v, variables));

	typedef typename mpl::if_<HasBase, degrees, mpl::vector<> >::type base_degrees;
	mpl::for_each<base_degrees>(put_base_degree_function<Graph>(g, v, variables, "orig_"));
    }

    template <class Graph>
    void populate_specific(const Graph& g, typename graph_traits<Graph>::edge_descriptor& e, const dynamic_properties& dp, python::object& variables)
    {
	typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;

	variables["is_loop"] = python::make_function(is_loop<Graph>(g, e), python::default_call_policies(), mpl::vector<python::object>::type()); 
77
	
78
79
80
	for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
	{
	    if (iter->second->key() == typeid(vertex_descriptor))
81
	    {
82
83
84
85
		variables["source_"+iter->first] = python::make_function(get_source_or_target_value<Graph,true>(g, *iter->second, e), 
									 python::default_call_policies(), mpl::vector<python::object>::type());
		variables["target_"+iter->first] = python::make_function(get_source_or_target_value<Graph,false>(g, *iter->second, e), 
									 python::default_call_policies(), mpl::vector<python::object>::type());
86
87
	    }
	}
88
89
	mpl::for_each<degrees>(put_source_or_target_degree_function<Graph,true>(g, e, variables, "source_"));
	mpl::for_each<degrees>(put_source_or_target_degree_function<Graph,false>(g, e, variables, "target_"));
90
    }
91
92


93
94
95
96
97
98
99
100
101
102
103
104
105
    template <class VertexOrEdge>
    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 <class Type>
	    void operator()(Type)
	    {
106
107
108
109
		any any_val = const_cast<dynamic_property_map&>(_parent._dmap).get(_parent._e);
		Type* value = any_cast<Type>(&any_val);
		if (value != 0)
		    _parent._retval = python::object(*value);
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
	    }
	    
	    get_value& _parent;
	};
	
	python::object operator()()
	{
	    typedef mpl::vector<bool,int,long,size_t,float,double,std::string> value_types;
	    mpl::for_each<value_types>(try_conversion(*this));
	    return _retval;
	}

	const dynamic_property_map& _dmap;
	const VertexOrEdge& _e;
	python::object _retval;
    };

127
    template <class Graph, bool Source>
128
129
    struct get_source_or_target_value
    {
130
131
132
	typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
	typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;

133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
	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<vertex_descriptor> get_value(_dmap, _s);
	    return get_value();
	}

	const Graph& _g;	
	const dynamic_property_map& _dmap;
	const edge_descriptor& _e;	
    };

154
    template <class Graph, class Degree>
155
156
    struct get_degree
    {
157
158
159
	typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;

	get_degree(const Graph& g, const vertex_descriptor& v)
160
161
162
163
164
165
166
	    : _g(g), _v(v) {}
		
	python::object operator()()
	{
	    return python::object(_degree(_v, _g));
	}

167
	const Graph& _g;
168
169
170
171
	const vertex_descriptor& _v;
	Degree _degree;
    };

172
    template <class Graph>
173
174
    struct put_degree_function
    {
175
176
	typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;

177
178
179
180
181
182
183
184
185
186
187
188
189
	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 <class Degree>
	void operator()(Degree degree)
	{
	    _variables[_prefix+degree.name()] =  python::make_function(get_degree<Graph,Degree>(_g, _v),
								       python::default_call_policies(), mpl::vector<python::object>::type());
	}
	const Graph& _g;
	const vertex_descriptor& _v;
	python::object& _variables;
	std::string _prefix;
    };
190
191
192

    template <class Graph>    
    struct put_base_degree_function: public put_degree_function<Graph>
193
    {
194
195
	typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;

196
	put_base_degree_function(const Graph& g, const vertex_descriptor& v, python::object& variables, std::string prefix = "")
197
	    : put_degree_function<Graph>(g, v, variables, prefix) {}
198
199
200
201
202
203
204
205
206

	template <class Degree>
	void operator()(Degree degree)
	{
	    this->_variables[this->_prefix+degree.name()] = python::make_function(get_degree<typename Graph::graph_type,Degree>(this->_g.m_g, this->_v),
										  python::default_call_policies(), mpl::vector<python::object>::type());
	}
    };

207
    template <class Graph, bool Source>
208
209
    struct put_source_or_target_degree_function
    {
210
211
212
	typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
	typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;

213
214
215
216
217
218
219
220
221
222
	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 <class Degree>
	void operator()(Degree d)
	{
	    vertex_descriptor v;	    
	    if (Source)
		v = source(_e, this->_g);
	    else
		v = target(_e, this->_g);
223
	    put_degree_function<Graph>(_g, v, _variables, _prefix)(d);
224
225
226
227
228
229
230
231
	}

	const Graph& _g;
	const edge_descriptor& _e;
	python::object& _variables;
	std::string _prefix;
    };

232
    template<class Graph>
233
234
    struct is_loop
    {
235
236
	typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;

237
238
239
240
241
242
243
244
245
246
	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;
    };
    

247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
};


//==============================================================================
// PythonFilter
//==============================================================================
template <class Graph, class Descriptor, class HasBase = mpl::bool_<false> >
class PythonFilter
{
public:
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
    typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;

    typedef mpl::vector<in_degreeS,out_degreeS,total_degreeS> 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<Descriptor, HasBase>()(*_g, _u, dp, variables);
    }
    
 
    inline bool operator() (Descriptor u) const
272
    {	      
273
	_u = u;
274
275
276
277
278
279
	return python::extract<bool>(_filter());
    }

private:
    Graph const*  _g;
    python::object _filter;
280
    static Descriptor _u;
281
282
};

283
284
template <class Graph, class Descriptor, class HasBase> 
Descriptor PythonFilter<Graph,Descriptor,HasBase>::_u;
285
286
287
288

} //graph_tool namespace

#endif