graph_properties.cc 7.5 KB
Newer Older
Tiago Peixoto's avatar
Tiago Peixoto committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// 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.

19
20
21
22
23
#include <boost/lambda/bind.hpp>

#include "graph.hh"
#include "histogram.hh"
#include "graph_filtering.hh"
24
#include "graph_python_filtering.hh"
25
#include "graph_selectors.hh"
Tiago Peixoto's avatar
Tiago Peixoto committed
26
27
#include "graph_properties.hh"

28
29
30
31
32
33
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;


Tiago Peixoto's avatar
Tiago Peixoto committed
34
35
36
//==============================================================================
// find_property_map(dp,name,key_type)
//==============================================================================
37
38
dynamic_property_map& 
graph_tool::find_property_map(const dynamic_properties& dp, string name, const type_info& key_type)
Tiago Peixoto's avatar
Tiago Peixoto committed
39
40
{
    for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
41
42
        if (iter->first == name && iter->second->key() == key_type)
            return *iter->second;
Tiago Peixoto's avatar
Tiago Peixoto committed
43

44
45
46
47
48
49
50
51
52
53
54
    throw property_not_found(name);
}

//==============================================================================
// RemoveVertexProperty(property)
//==============================================================================
void GraphInterface::RemoveVertexProperty(string property)
{
    dynamic_properties_copy dp;
    try
    {
55
56
57
58
        dynamic_property_map& prop_map = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::vertex_descriptor));
        for (typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
        {
            if (iter->second != &prop_map)
59
                dp.insert(iter->first, auto_ptr<dynamic_property_map>(iter->second));
60
        }
61
62
63
    }
    catch (property_not_found)
    {
64
        throw GraphException("property '" + property + "' not found");
65
66
67
68
69
70
71
72
73
74
75
76
    }
    _properties = dp;
}

//==============================================================================
// RemoveEdgeProperty(property)
//==============================================================================
void GraphInterface::RemoveEdgeProperty(string property)
{
    dynamic_properties_copy dp;
    try
    {
77
78
79
80
        dynamic_property_map& prop_map = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::edge_descriptor));
        for (typeof(_properties.begin()) iter = _properties.begin(); iter != _properties.end(); ++iter)
        {
            if (iter->second != &prop_map)
81
                dp.insert(iter->first, auto_ptr<dynamic_property_map>(iter->second));
82
        }
83
84
85
    }
    catch (property_not_found)
    {
86
        throw GraphException("property '" + property + "' not found");
87
88
89
90
91
92
93
94
95
96
97
98
99
    }
    _properties = dp;
}

//==============================================================================
// edit_property
//==============================================================================
template <class Descriptor>
struct edit_property
{
    template <class Graph, class PropertyMap>
    void operator()(const Graph& g, const dynamic_properties& dp, PropertyMap prop_map, python::object& op) const
    {
100
        typedef mpl::vector<in_degreeS,out_degreeS,total_degreeS> degrees;
101

102
        python::object operation = op[0], variables = op[1];
103

104
105
        typedef typename graph_traits<Graph>::vertex_descriptor vertex_descriptor;
        typedef typename graph_traits<Graph>::edge_descriptor edge_descriptor;
106

107
        typedef typename mpl::if_<is_same<Descriptor,vertex_descriptor>,vertex_descriptor,edge_descriptor>::type descriptor_t;
108
        descriptor_t u;
109
110
        
        populate_python_funcs<descriptor_t>()(g, u, dp, variables);
111

112
        put_properties(g, u, prop_map, operation);
113
114
115
116
    }
    
    template<class Graph, class PropertyMap>
    void put_properties(const Graph& g, typename graph_traits<Graph>::vertex_descriptor& v, 
117
                        PropertyMap prop_map, python::object& operation) const
118
    {
119
120
121
122
123
124
125
        typename graph_traits<Graph>::vertex_iterator vi,v_end;
        for (tie(vi, v_end) = vertices(g); vi != v_end; ++vi)
        {
            v = *vi;
            typename property_traits<PropertyMap>::value_type val = python::extract<typename property_traits<PropertyMap>::value_type>(operation());
            put(prop_map, v, val);
        }
126
127
128
129
    }

    template<class Graph, class PropertyMap>
    void put_properties(const Graph& g, typename graph_traits<Graph>::edge_descriptor& e, 
130
                        PropertyMap prop_map, python::object& operation) const
131
    {
132
133
134
135
136
137
138
        typename graph_traits<Graph>::edge_iterator ei,e_end;
        for (tie(ei, e_end) = edges(g); ei != e_end; ++ei)
        {
            e = *ei;
            typename property_traits<PropertyMap>::value_type val = python::extract<typename property_traits<PropertyMap>::value_type>(operation());
            put(prop_map, e, val);
        }
139
140
141
142
143
144
145
146
147
148
149
150
151
152
    }
    

};

//==============================================================================
// EditVertexProperty()
//==============================================================================

void GraphInterface::EditVertexProperty(string property, python::object op)
{
    typedef graph_traits<multigraph_t>::vertex_descriptor vertex_descriptor;
    try
    {
153
154
155
156
        dynamic_property_map& dpmap = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::vertex_descriptor));
        typedef DynamicPropertyMapWrap<double,vertex_descriptor> prop_map_t;
        prop_map_t prop_map(dpmap);
        check_filter(*this, bind<void>(edit_property<vertex_descriptor>(), _1, var(_properties), prop_map, var(op)),
157
                     reverse_check(), directed_check());
158
159
160
    }
    catch (property_not_found)
    {
161
162
163
        typedef vector_property_map<double, vertex_index_map_t> prop_map_t;
        prop_map_t prop_map(_vertex_index);
        check_filter(*this, bind<void>(edit_property<vertex_descriptor>(), _1, var(_properties), prop_map, var(op)),
164
                     reverse_check(), directed_check());
165
        _properties.property(property, prop_map);
166
167
168
169
170
171
172
173
    }    
}

void GraphInterface::EditEdgeProperty(string property, python::object op)
{
    typedef graph_traits<multigraph_t>::edge_descriptor edge_descriptor;
    try
    {
174
175
176
177
        dynamic_property_map& dpmap = find_property_map(_properties, property, typeid(graph_traits<multigraph_t>::edge_descriptor));
        typedef DynamicPropertyMapWrap<double,edge_descriptor> prop_map_t;
        prop_map_t prop_map(dpmap);
        check_filter(*this, bind<void>(edit_property<edge_descriptor>(), _1, var(_properties), prop_map, var(op)),
178
                     reverse_check(), directed_check());
179
180
181
    }
    catch (property_not_found)
    {
182
183
184
        typedef vector_property_map<double, edge_index_map_t> prop_map_t;
        prop_map_t prop_map(_edge_index);
        check_filter(*this, bind<void>(edit_property<edge_descriptor>(), _1, var(_properties), prop_map, var(op)),
185
                     reverse_check(), directed_check());
186
        _properties.property(property, prop_map);
187
    }
Tiago Peixoto's avatar
Tiago Peixoto committed
188
}