graph_python_interface.hh 5.89 KB
Newer Older
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>
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
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
// along with this program. If not, see <http://www.gnu.org/licenses/>.
17

18
19
#ifndef PYTHON_INTERFACE_HH
#define PYTHON_INTERFACE_HH
20

21
#include <boost/python.hpp>
22
23
#include <boost/graph/graph_traits.hpp>
#include <boost/mpl/logical.hpp>
24
#include <boost/functional/hash.hpp>
25
#include <boost/iterator/iterator_facade.hpp>
26

27
#include "graph_selectors.hh"
28

29
// this file includes a simple python interface for the internally kept
30
31
32
33
// graph. It defines a PythonVertex, PythonEdge and PythonIterator template
// classes, which contain the proper member functions for graph traversal. These
// types are then specialized for each version of the adapted graph (directed,
// undirected, filtered, reversed).
34

35
36
37
38
namespace graph_tool
{
using namespace boost;

39
40
41
42
// generic iterator adaptor which can be used to iterate vertices, edges,
// out_edges and in_edges through python
template <class Graph, class Descriptor, class Iterator>
class PythonIterator
43
{
44
public:
45
46
47
    PythonIterator(const Graph& g, std::pair<Iterator,Iterator> e)
        : _g(g), _e(e) {}
    Descriptor Next()
48
    {
49
50
51
52
53
        if (_e.first == _e.second)
            python::objects::stop_iteration_error();
        Descriptor e(_g, *_e.first);
        ++_e.first;
        return e;
54
55
    }
private:
56
57
    const Graph& _g;
    std::pair<Iterator,Iterator> _e;
Tiago Peixoto's avatar
Tiago Peixoto committed
58
59
60
};


61
// forward declaration of PythonEdge
62
63
template <class Graph>
class PythonEdge;
64

65
// below are classes related to the PythonVertex type
66
template <class Graph>
67
    class PythonVertex
68
69
70
71
{
public:
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
    typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
72

73
74
    PythonVertex(const Graph& g, vertex_descriptor v):
        _g(g), _v(v) {}
75

76
    PythonVertex(const PythonVertex& v): _g(v._g)
77
    {
78
        _v = v._v;
79
    }
80

81
82
83
84
85
    const vertex_descriptor& GetDescriptor() const
    {
        return _v;
    }

86
    size_t GetInDegree() const
87
    {
88
        return in_degreeS()(_v, _g);
89
    }
90

91
    size_t GetOutDegree() const
92
    {
93
        return out_degreeS()(_v, _g);
Tiago Peixoto's avatar
Tiago Peixoto committed
94
95
    }

96
    // provide iterator support for out_edges
Tiago Peixoto's avatar
Tiago Peixoto committed
97
98

    typedef typename graph_traits<Graph>::out_edge_iterator out_edge_iterator;
99
100
    PythonIterator<Graph,PythonEdge<Graph>,out_edge_iterator>
    OutEdges() const
Tiago Peixoto's avatar
Tiago Peixoto committed
101
    {
102
103
        return PythonIterator<Graph,PythonEdge<Graph>,out_edge_iterator>
            (_g, out_edges(_v, _g));
104
    }
105

106
107
108
    typedef typename in_edge_iteratorS<Graph>::type in_edge_iterator;
    PythonIterator<Graph,PythonEdge<Graph>, in_edge_iterator>
    InEdges() const
109
    {
110
        return PythonIterator<Graph,PythonEdge<Graph>,in_edge_iterator>
111
            (_g, in_edge_iteratorS<Graph>::get_edges(_v, _g));
Tiago Peixoto's avatar
Tiago Peixoto committed
112
113
    }

114
115
116
117
118
    std::string GetString() const
    {
        return lexical_cast<std::string>(_v);
    }

119
    size_t GetHash() const
120
    {
121
        return hash<vertex_descriptor>()(_v);
122
123
    }

124
    bool operator==(const PythonVertex& other) const
125
    {
126
        return other._v == _v;
127
    }
128

129
    bool operator!=(const PythonVertex& other) const
130
    {
131
        return other._v != _v;
132
133
    }

134
private:
135
136
    const Graph& _g;
    vertex_descriptor _v;
137
};
138

139
// below are classes related to the PythonEdge type
140

141
142
143
144
template <class Graph>
class PythonEdge
{
public:
Tiago Peixoto's avatar
Tiago Peixoto committed
145
146
147
    typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
    typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;

148
149
    PythonEdge(const Graph& g, edge_descriptor e): _g(g), _e(e) {}
    PythonEdge(const PythonEdge& e): _g(e._g)
Tiago Peixoto's avatar
Tiago Peixoto committed
150
    {
151
        _e = e._e;
Tiago Peixoto's avatar
Tiago Peixoto committed
152
153
    }

154
155
156
157
158
    const edge_descriptor& GetDescriptor() const
    {
        return _e;
    }

159
    PythonVertex<Graph> GetSource() const
Tiago Peixoto's avatar
Tiago Peixoto committed
160
    {
161
        return PythonVertex<Graph>(_g, source(_e, _g));
Tiago Peixoto's avatar
Tiago Peixoto committed
162
163
    }

164
    PythonVertex<Graph> GetTarget() const
Tiago Peixoto's avatar
Tiago Peixoto committed
165
    {
166
        return PythonVertex<Graph>(_g, target(_e, _g));
Tiago Peixoto's avatar
Tiago Peixoto committed
167
168
    }

169
170
171
172
173
174
    std::string GetString() const
    {
        return "("+GetSource().GetString() + "," +
            GetTarget().GetString() + ")";
    }

175
    size_t GetHash() const
Tiago Peixoto's avatar
Tiago Peixoto committed
176
    {
177
178
179
180
181
        vertex_descriptor s,t;
        s = source(_e, _g);
        t = target(_e, _g);
        return hash<std::pair<vertex_descriptor, vertex_descriptor> >()
            (make_pair(s,t));
Tiago Peixoto's avatar
Tiago Peixoto committed
182
183
    }

184
    bool operator==(const PythonEdge& other) const
Tiago Peixoto's avatar
Tiago Peixoto committed
185
    {
186
        return other._e == _e;
Tiago Peixoto's avatar
Tiago Peixoto committed
187
    }
188

189
    bool operator!=(const PythonEdge& other) const
190
    {
191
        return other._e != _e;
192
193
194
    }

private:
195
196
    const Graph& _g;
    edge_descriptor _e;
197
198
};

199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
template <class ValueType>
class PythonPropertyMap
{
public:
    PythonPropertyMap(const std::string& name, dynamic_property_map& pmap)
        : _name(name), _pmap(pmap) {}

    template <class PythonDescriptor>
    ValueType GetValue(const PythonDescriptor& key) const
    {
        any val = _pmap.get(key.GetDescriptor());
        return any_cast<ValueType>(val);
    }

    template <class PythonDescriptor>
    void SetValue(const PythonDescriptor& key, const ValueType& val)
    {
        _pmap.put(key.GetDescriptor(), val);
    }

    size_t GetHash() const
    {
        return hash<std::string>()(_name + this->GetType());
    }

    std::string GetType() const
    {
        return type_names[mpl::find<value_types,ValueType>::type::pos::value];
    }

private:
    const std::string& _name;
    dynamic_property_map& _pmap;
};


235
236
237
} //graph_tool namespace

#endif