graph_bind.cc 15.2 KB
Newer Older
Tiago Peixoto's avatar
Tiago Peixoto committed
1
2
// graph-tool -- a general graph modification and manipulation thingy
//
Tiago Peixoto's avatar
Tiago Peixoto committed
3
// Copyright (C) 2007  Tiago de Paula Peixoto <tiago@forked.de>
Tiago Peixoto's avatar
Tiago Peixoto committed
4
5
6
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
Tiago Peixoto's avatar
Tiago Peixoto committed
7
// as published by the Free Software Foundation; either version 3
Tiago Peixoto's avatar
Tiago Peixoto committed
8
9
10
11
12
13
14
15
// 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
16
17
// along with this program. If not, see <http://www.gnu.org/licenses/>.

Tiago Peixoto's avatar
Tiago Peixoto committed
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

#include <boost/python.hpp>
#include <boost/tuple/tuple.hpp>
#include "graph.hh"

using namespace std;
using namespace graph_tool;
using namespace boost;
using namespace boost::python;

// some conversions...

template <class T1, class T2>
struct pair_to_tuple
{
    static PyObject* convert(const pair<T1,T2>& p)
    {
35
36
        boost::python::tuple t = boost::python::make_tuple(p.first,p.second);
        return incref(t.ptr());
Tiago Peixoto's avatar
Tiago Peixoto committed
37
38
39
40
41
42
43
44
    }
};

template <class T1, class T2, class T3>
struct tuple_to_tuple
{
    static PyObject* convert(const boost::tuple<T1,T2,T3>& p)
    {
45
46
        boost::python::tuple t = 
            boost::python::make_tuple(get<0>(p),get<1>(p),get<2>(p));
47
        return incref(t.ptr());
Tiago Peixoto's avatar
Tiago Peixoto committed
48
49
50
51
52
53
54
55
56
    }
};


template <class T1, class T2, class T3>
struct tuple_from_tuple
{
    tuple_from_tuple()
    {
57
58
59
        converter::registry::push_back
            (&convertible, &construct,  
             boost::python::type_id<boost::tuple<T1,T2,T3> >());
Tiago Peixoto's avatar
Tiago Peixoto committed
60
61
62
63
    }

    static void* convertible(PyObject* obj_ptr)
    {
64
65
66
67
68
69
70
71
        handle<> x(borrowed(obj_ptr));
        object o(x);
        extract<T1> first(o[0]);
        extract<T2> second(o[1]);
        extract<T2> third(o[3]);
        if (!first.check() || !second.check() || !third.check()) 
            return 0;
        return obj_ptr;
Tiago Peixoto's avatar
Tiago Peixoto committed
72
73
    }

74
75
    static void construct(PyObject* obj_ptr, 
                          converter::rvalue_from_python_stage1_data* data)
76
77
78
79
80
81
82
    {          
        handle<> x(borrowed(obj_ptr));
        object o(x);
        boost::tuple<T1,T2,T3> value;
        get<0>(value) = extract<T1>(o[0]);
        get<1>(value) = extract<T2>(o[1]);
        get<2>(value) = extract<T2>(o[2]);
83
84
85
        void* storage = 
            ((boost::python::converter::rvalue_from_python_storage
              <boost::tuple<T1,T2,T3> >*) data)->storage.bytes;
86
87
        new (storage) boost::tuple<T1,T2,T3>(value);
        data->convertible = storage;
Tiago Peixoto's avatar
Tiago Peixoto committed
88
89
90
91
92
93
94
95
    }
};

template <class T1, class T2>
struct pair_from_tuple
{
    pair_from_tuple()
    {
96
97
        converter::registry::push_back(&convertible, &construct,  
                                       boost::python::type_id<pair<T1,T2> >());
Tiago Peixoto's avatar
Tiago Peixoto committed
98
99
100
101
    }

    static void* convertible(PyObject* obj_ptr)
    {
102
103
104
105
106
107
108
        handle<> x(borrowed(obj_ptr));
        object o(x);
        extract<T1> first(o[0]);
        extract<T2> second(o[1]);
        if (!first.check() || !second.check()) 
            return 0;
        return obj_ptr;
Tiago Peixoto's avatar
Tiago Peixoto committed
109
110
    }

111
112
    static void construct(PyObject* obj_ptr, 
                          converter::rvalue_from_python_stage1_data* data)
113
114
115
116
117
118
    {          
        handle<> x(borrowed(obj_ptr));
        object o(x);
        pair<T1,T2> value;
        value.first = extract<T1>(o[0]);
        value.second = extract<T2>(o[1]);
119
120
121
        void* storage = 
            ( (boost::python::converter::rvalue_from_python_storage
               <pair<T1,T2> >*) data)->storage.bytes;
122
123
        new (storage) pair<T1,T2>(value);
        data->convertible = storage;
Tiago Peixoto's avatar
Tiago Peixoto committed
124
125
126
127
128
129
130
131
    }
};

template <class ValueType> 
struct variant_from_python
{
    variant_from_python()
    {
132
133
134
        converter::registry::push_back
            (&convertible, &construct, 
             boost::python::type_id<GraphInterface::deg_t>());
Tiago Peixoto's avatar
Tiago Peixoto committed
135
136
137
138
    }

    static void* convertible(PyObject* obj_ptr)
    {
139
140
141
142
143
144
        handle<> x(borrowed(obj_ptr));
        object o(x);
        extract<ValueType> str(o);
        if (!str.check())
            return 0;
        return obj_ptr;
Tiago Peixoto's avatar
Tiago Peixoto committed
145
146
    }

147
148
    static void construct(PyObject* obj_ptr, 
                          converter::rvalue_from_python_stage1_data* data)
149
150
151
152
153
    {          
        handle<> x(borrowed(obj_ptr));
        object o(x);
        ValueType value = extract<ValueType>(o);
        GraphInterface::deg_t deg = value;
154
155
156
        void* storage = 
            ( (boost::python::converter::rvalue_from_python_storage
               <GraphInterface::deg_t>*) data)->storage.bytes;
157
158
        new (storage) GraphInterface::deg_t(deg);
        data->convertible = storage;
Tiago Peixoto's avatar
Tiago Peixoto committed
159
160
161
162
163
164
165
166
167
168
    }
};



template <class Hist>
struct hist_to_dict
{
    static PyObject* convert(const Hist& h)
    {
169
170
171
172
        dict hist;
        for(typeof(h.begin()) iter = h.begin(); iter != h.end(); ++iter)
            hist[iter->first] = iter->second;
        return incref(hist.ptr());
Tiago Peixoto's avatar
Tiago Peixoto committed
173
174
175
    }
};

176
177
178
179
180
181
182
183
184
185
186
187
188
struct pos_t_to_tuple
{
    static PyObject* convert(const pos_t& p)
    {
        boost::python::tuple t = boost::python::make_tuple(p.x,p.y);
        return incref(t.ptr());
    }
};

struct pos_t_from_tuple
{
    pos_t_from_tuple()
    {
189
190
        converter::registry::push_back(&convertible, &construct,  
                                       boost::python::type_id<pos_t>());
191
192
193
194
195
196
197
198
199
200
201
202
203
    }

    static void* convertible(PyObject* obj_ptr)
    {
        handle<> x(borrowed(obj_ptr));
        object o(x);
        extract<double> first(o[0]);
        extract<double> second(o[1]);
        if (!first.check() || !second.check()) 
            return 0;
        return obj_ptr;
    }

204
205
    static void construct(PyObject* obj_ptr, 
                          converter::rvalue_from_python_stage1_data* data)
206
207
208
209
210
211
    {          
        handle<> x(borrowed(obj_ptr));
        object o(x);
        pos_t value;
        value.x = extract<double>(o[0]);
        value.y = extract<double>(o[1]);
212
213
214
        void* storage = 
            ( (boost::python::converter::rvalue_from_python_storage
               <pos_t>*) data)->storage.bytes;
215
216
217
218
219
        new (storage) pos_t(value);
        data->convertible = storage;
    }
};

Tiago Peixoto's avatar
Tiago Peixoto committed
220
221
222
223

class GraphInterfaceWrap: public GraphInterface
{
public:
224
225
226
227
228
229
230
231
    void GenerateCorrelatedConfigurationalModel(size_t N, object pjk, 
                                                object ceil_pjk, 
                                                object inv_ceil_pjk, 
                                                double ceil_pjk_bound,
                                                object corr, object ceil_corr, 
                                                object inv_ceil_corr, 
                                                double ceil_corr_bound, 
                                                bool undirected_corr, 
232
                                                size_t seed, bool verbose) 
Tiago Peixoto's avatar
Tiago Peixoto committed
233
    {
234
        GraphInterface& base = *this;
235
236
237
238
239
240
241
        base.GenerateCorrelatedConfigurationalModel
            (N, pjk_t(python_function(pjk)), pjk_t(python_function(ceil_pjk)), 
             inv_ceil_t(python_function(inv_ceil_pjk)),
             ceil_pjk_bound, corr_t(python_function(corr)), 
             corr_t(python_function(ceil_corr)), 
             inv_corr_t(python_function(inv_ceil_corr)), 
             ceil_corr_bound, undirected_corr, seed, verbose);
Tiago Peixoto's avatar
Tiago Peixoto committed
242
243
244
245
    }

    struct python_function
    {
246
247
248
249
250
251
252
253
254
255
256
257
        python_function(object o): _o(o) {}
        double operator()(size_t j, size_t k)
        {
            return extract<double>(_o(j,k));
        }
        double operator()(size_t jl, size_t kl, size_t j, size_t k)
        {
            return extract<double>(_o(jl,kl,j,k));
        }
        pair<size_t,size_t> operator()(double r1, double r2)
        {
            object retval = _o(r1,r2);
258
259
            return make_pair(size_t(max(int(extract<int>(retval[0])),0)), 
                             size_t(max(int(extract<int>(retval[1])),0)));
260
261
262
263
        }
        pair<size_t,size_t> operator()(double r1, double r2, size_t j, size_t k)
        {
            object retval = _o(r1,r2,j,k);
264
265
            return make_pair(size_t(max(int(extract<int>(retval[0])),0)), 
                             size_t(max(int(extract<int>(retval[1])),0)));
266
267
        }
        object _o;
Tiago Peixoto's avatar
Tiago Peixoto committed
268
269
270
271
272
273
274
275
276
    };

};

struct LibInfo
{
    string GetName()      const {return PACKAGE_NAME;}
    string GetAuthor()    const {return AUTHOR;}
    string GetCopyright() const {return COPYRIGHT;}
277
    string GetVersion()   const {return VERSION " (commit " GIT_COMMIT ", " GIT_COMMIT_DATE ")";}
278
    string GetLicense()   const {return "GPL version 3 or above";}
Tiago Peixoto's avatar
Tiago Peixoto committed
279
280
};

Tiago Peixoto's avatar
Tiago Peixoto committed
281
// overloads
282
283
284
285
286
287
288
289
void  (GraphInterfaceWrap::*ReadFromFile1) (string) =
    &GraphInterfaceWrap::ReadFromFile;
void  (GraphInterfaceWrap::*ReadFromFile2) (string, string) =
    &GraphInterfaceWrap::ReadFromFile;
void  (GraphInterfaceWrap::*WriteToFile1)  (string) =
    &GraphInterfaceWrap::WriteToFile;
void  (GraphInterfaceWrap::*WriteToFile2)  (string, string)  = 
    &GraphInterfaceWrap::WriteToFile;
Tiago Peixoto's avatar
Tiago Peixoto committed
290
291


Tiago Peixoto's avatar
Tiago Peixoto committed
292
293
294
BOOST_PYTHON_MODULE(libgraph_tool)
{
    class_<GraphInterfaceWrap>("GraphInterface")
295
296
        .def("GenerateCorrelatedConfigurationalModel", 
             &GraphInterfaceWrap::GenerateCorrelatedConfigurationalModel)
297
298
299
300
301
302
        .def("GetNumberOfVertices", &GraphInterfaceWrap::GetNumberOfVertices)
        .def("GetNumberOfEdges", &GraphInterfaceWrap::GetNumberOfEdges)
        .def("GetVertexHistogram", &GraphInterfaceWrap::GetVertexHistogram)
        .def("GetEdgeHistogram", &GraphInterfaceWrap::GetEdgeHistogram)
        .def("LabelComponents", &GraphInterfaceWrap::LabelComponents)
        .def("LabelParallelEdges", &GraphInterfaceWrap::LabelParallelEdges)
303
304
305
306
307
308
309
310
311
312
313
314
315
316
        .def("GetCombinedVertexHistogram",
             &GraphInterfaceWrap::GetCombinedVertexHistogram)
        .def("GetAverageCombinedVertexCorrelation", 
             &GraphInterfaceWrap::GetAverageCombinedVertexCorrelation)
        .def("GetVertexCorrelationHistogram", 
             &GraphInterfaceWrap::GetVertexCorrelationHistogram)
        .def("GetEdgeVertexCorrelationHistogram", 
             &GraphInterfaceWrap::GetEdgeVertexCorrelationHistogram)
        .def("GetAverageNearestNeighboursCorrelation", 
             &GraphInterfaceWrap::GetAverageNearestNeighboursCorrelation)
        .def("GetAssortativityCoefficient", 
             &GraphInterfaceWrap::GetAssortativityCoefficient)
        .def("GetScalarAssortativityCoefficient", 
             &GraphInterfaceWrap::GetScalarAssortativityCoefficient)
317
        .def("GetGlobalClustering", &GraphInterfaceWrap::GetGlobalClustering)
318
319
320
321
        .def("SetLocalClusteringToProperty",
             &GraphInterfaceWrap::SetLocalClusteringToProperty)
        .def("SetExtendedClusteringToProperty",
             &GraphInterfaceWrap::SetExtendedClusteringToProperty)
322
        .def("GetDistanceHistogram", &GraphInterfaceWrap::GetDistanceHistogram)
323
324
        .def("GetSampledDistanceHistogram", 
             &GraphInterfaceWrap::GetSampledDistanceHistogram)
325
        .def("GetReciprocity", &GraphInterfaceWrap::GetReciprocity)
326
327
        .def("GetMinimumSpanningTree", 
             &GraphInterfaceWrap::GetMinimumSpanningTree)
328
        .def("GetLineGraph", &GraphInterfaceWrap::GetLineGraph)
329
        .def("GetBetweenness", &GraphInterfaceWrap::GetBetweenness)
330
331
332
333
        .def("GetCentralPointDominance", 
             &GraphInterfaceWrap::GetCentralPointDominance)
        .def("GetCommunityStructure",
             &GraphInterfaceWrap::GetCommunityStructure)
334
335
336
337
338
339
        .def("GetCommunityNetwork", &GraphInterfaceWrap::GetCommunityNetwork)
        .def("GetModularity", &GraphInterfaceWrap::GetModularity)
        .def("SetDirected", &GraphInterfaceWrap::SetDirected)
        .def("GetDirected", &GraphInterfaceWrap::GetDirected)
        .def("SetReversed", &GraphInterfaceWrap::SetReversed)
        .def("GetReversed", &GraphInterfaceWrap::GetReversed)
340
341
        .def("SetVertexFilterProperty", 
             &GraphInterfaceWrap::SetVertexFilterProperty)
342
        .def("SetVertexFilterRange", &GraphInterfaceWrap::SetVertexFilterRange)
343
        .def("IsVertexFilterActive", &GraphInterfaceWrap::IsVertexFilterActive)
344
345
        .def("SetEdgeFilterProperty",
             &GraphInterfaceWrap::SetEdgeFilterProperty)
346
347
348
349
        .def("SetEdgeFilterRange", &GraphInterfaceWrap::SetEdgeFilterRange)
        .def("IsEdgeFilterActive", &GraphInterfaceWrap::IsEdgeFilterActive)
        .def("EditEdgeProperty",  &GraphInterfaceWrap::EditEdgeProperty)
        .def("EditVertexProperty",  &GraphInterfaceWrap::EditVertexProperty)
Tiago Peixoto's avatar
Tiago Peixoto committed
350
        .def("EditGraphProperty",  &GraphInterfaceWrap::EditGraphProperty)
351
352
        .def("RemoveEdgeProperty",  &GraphInterfaceWrap::RemoveEdgeProperty)
        .def("RemoveVertexProperty",  &GraphInterfaceWrap::RemoveVertexProperty)
Tiago Peixoto's avatar
Tiago Peixoto committed
353
        .def("RemoveGraphProperty",  &GraphInterfaceWrap::RemoveGraphProperty)
354
        .def("ListProperties",  &GraphInterfaceWrap::ListProperties)
355
356
        .def("PurgeVertices",  &GraphInterfaceWrap::PurgeVertices)
        .def("PurgeEdges",  &GraphInterfaceWrap::PurgeEdges)
357
358
359
360
361
362
363
364
        .def("InsertEdgeIndexProperty",  
             &GraphInterfaceWrap::InsertEdgeIndexProperty)
        .def("InsertVertexIndexProperty", 
             &GraphInterfaceWrap::InsertVertexIndexProperty)
        .def("ComputeGraphLayoutGursoy", 
             &GraphInterfaceWrap::ComputeGraphLayoutGursoy)
        .def("ComputeGraphLayoutSpringBlock", 
             &GraphInterfaceWrap::ComputeGraphLayoutSpringBlock)
365
366
367
368
369
370
        .def("WriteToFile", WriteToFile1)
        .def("WriteToFile", WriteToFile2)
        .def("ReadFromFile", ReadFromFile1)
        .def("ReadFromFile", ReadFromFile2)
        .def("InitSignalHandling", &GraphInterfaceWrap::InitSignalHandling);
        
Tiago Peixoto's avatar
Tiago Peixoto committed
371
    enum_<GraphInterfaceWrap::degree_t>("Degree")
372
373
374
        .value("In", GraphInterfaceWrap::IN_DEGREE)
        .value("Out", GraphInterfaceWrap::OUT_DEGREE)
        .value("Total", GraphInterfaceWrap::TOTAL_DEGREE);
Tiago Peixoto's avatar
Tiago Peixoto committed
375

Tiago Peixoto's avatar
Tiago Peixoto committed
376
    enum_<GraphInterfaceWrap::comm_corr_t>("CommCorr")
377
378
379
        .value("ErdosReyni", GraphInterfaceWrap::ERDOS_REYNI)
        .value("Uncorrelated", GraphInterfaceWrap::UNCORRELATED)
        .value("Correlated", GraphInterfaceWrap::CORRELATED);
Tiago Peixoto's avatar
Tiago Peixoto committed
380

Tiago Peixoto's avatar
Tiago Peixoto committed
381
382
383
384
    variant_from_python<string>();
    variant_from_python<GraphInterfaceWrap::degree_t>();
    to_python_converter<pair<double,double>, pair_to_tuple<double,double> >();
    pair_from_tuple<double,double>();
385
386
    to_python_converter<boost::tuple<double,double,double>, 
                        tuple_to_tuple<double,double,double> >();
Tiago Peixoto's avatar
Tiago Peixoto committed
387
    tuple_from_tuple<double,double,double>();
388
389
    to_python_converter<pos_t, pos_t_to_tuple>();
    pos_t_from_tuple();
390
    pair_from_tuple<bool,bool>();
391
392
393
394
395
396
397
398
    to_python_converter<GraphInterfaceWrap::hist_t, 
                        hist_to_dict<GraphInterfaceWrap::hist_t> >();
    to_python_converter<GraphInterfaceWrap::hist2d_t, 
                        hist_to_dict<GraphInterfaceWrap::hist2d_t> >();
    to_python_converter<GraphInterfaceWrap::hist3d_t, 
                        hist_to_dict<GraphInterfaceWrap::hist3d_t> >();
    to_python_converter<GraphInterfaceWrap::avg_corr_t, 
                        hist_to_dict<GraphInterfaceWrap::avg_corr_t> >();
Tiago Peixoto's avatar
Tiago Peixoto committed
399
400

    class_<LibInfo>("mod_info")
401
402
403
        .add_property("name", &LibInfo::GetName)
        .add_property("author", &LibInfo::GetAuthor)
        .add_property("copyright", &LibInfo::GetCopyright)
404
405
        .add_property("version", &LibInfo::GetVersion)
        .add_property("license", &LibInfo::GetLicense);
Tiago Peixoto's avatar
Tiago Peixoto committed
406
}