graph_properties.cc 9.62 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
#include "graph_properties.hh"
19
#include "graph_util.hh"
Tiago Peixoto's avatar
Tiago Peixoto committed
20

21
#include <boost/lambda/bind.hpp>
22
23
#include <boost/mpl/for_each.hpp>

24
25
26
27
28
using namespace std;
using namespace boost;
using namespace boost::lambda;
using namespace graph_tool;

29
30
namespace graph_tool
{
31

32
// global property types' names
33
const char* type_names[] =
34
35
    {"bool", "int32_t", "int64_t", "double", "long double",
     "string", "vector<bool>","vector<int32_t>", "vector<int64_t>",
36
37
     "vector<double>", "vector<long double>", "vector<string>",
     "python::object"};
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102


PropertyNotFound::PropertyNotFound(const string& name, const type_info& key,
                                   const string& extra_info)
    : GraphException("")
{
    string key_type;
    if  (key == typeid(GraphInterface::edge_t))
        key_type = "edge";
    else if (key == typeid(GraphInterface::vertex_t))
        key_type = "vertex";
    else if (key == typeid(graph_property_tag))
        key_type = "graph";
    else
        key_type = "unknown";
    string error = "no " + key_type + " property map named \"" + name +
        "\" found";
    if (extra_info != "")
        error += "\n\n" + extra_info;
    this->SetError(error);
}

PropertyNotFound::PropertyNotFound(const string& name, const type_info& key,
                                   const type_info& value,
                                   const string& extra_info)
    : GraphException("")
{
    string key_type;
    if  (key == typeid(GraphInterface::edge_t))
        key_type = "edge";
    else if (key == typeid(GraphInterface::vertex_t))
        key_type = "vertex";
    else if (key == typeid(graph_property_tag))
        key_type = "graph";
    else
        key_type = "unknown";
    string error = "no " + key_type + " property map named \"" + name +
        "\", of value type " + get_type_name<>()(value) + " found";
    if (extra_info != "")
        error += "\n\n" + extra_info;
    this->SetError(error);
}

PropertyNotFound::PropertyNotFound(const string& name, const type_info& key,
                                   const vector<string>& values,
                                   const string& extra_info)
    : GraphException("")
{
    string key_type;
    if  (key == typeid(GraphInterface::edge_t))
        key_type = "edge";
    else if (key == typeid(GraphInterface::vertex_t))
        key_type = "vertex";
    else if (key == typeid(graph_property_tag))
        key_type = "graph";
    else
        key_type = "unknown";
    string error = "no " + key_type + " property map named \"" + name +
        "\", with any of the following value types found:";
    for (size_t i = 0; i < values.size(); ++i)
        error += " " + values[i];
    if (extra_info != "")
        error += "\n\n" + extra_info;
    this->SetError(error);
}
103

104
105
// this function gets the dynamic property map inside dp which matches the given
// name and key type
106
dynamic_property_map&
107
find_property_map(const dynamic_properties& dp, const string& name,
108
                  const type_info& key_type)
Tiago Peixoto's avatar
Tiago Peixoto committed
109
110
{
    for(typeof(dp.begin()) iter = dp.begin(); iter != dp.end(); ++iter)
111
112
        if (iter->first == name && iter->second->key() == key_type)
            return *iter->second;
Tiago Peixoto's avatar
Tiago Peixoto committed
113

114
    throw PropertyNotFound(name, key_type);
115
116
}

117
118
boost::any vertex_prop(const string& name, const GraphInterface& gi,
                       bool dynamic)
119
{
120
    return prop(name, gi._vertex_index, gi._properties, dynamic);
121
}
122
123
boost::any edge_prop(const string& name, const GraphInterface& gi,
                     bool dynamic)
124
{
125
    return prop(name, gi._edge_index, gi._properties, dynamic);
126
127
}

128
129
boost::any graph_prop(const string& name, const GraphInterface& gi,
                      bool dynamic)
130
131
{
    ConstantPropertyMap<size_t,graph_property_tag> graph_index(0);
132
    return prop(name, graph_index, gi._properties, dynamic);
133
134
}

135
136
137
void GraphInterface::RemoveVertexProperty(string property)
{
    dynamic_properties_copy dp;
138
139
140
141
    dynamic_property_map& prop_map =
        find_property_map(_properties, property, typeid(vertex_t));
    for (typeof(_properties.begin()) iter = _properties.begin();
         iter != _properties.end(); ++iter)
142
    {
143
144
145
        if (iter->second != &prop_map)
            dp.insert(iter->first,
                      auto_ptr<dynamic_property_map>(iter->second));
146
147
    }
    _properties = dp;
148
149
    if (_vertex_filter_property == property)
        SetVertexFilterProperty("",true);
150
151
152
153
154
}

void GraphInterface::RemoveEdgeProperty(string property)
{
    dynamic_properties_copy dp;
155
156
157
158
    dynamic_property_map& prop_map =
        find_property_map(_properties, property, typeid(edge_t));
    for (typeof(_properties.begin()) iter = _properties.begin();
         iter != _properties.end(); ++iter)
159
    {
160
161
162
        if (iter->second != &prop_map)
            dp.insert(iter->first,
                      auto_ptr<dynamic_property_map>(iter->second));
163
164
    }
    _properties = dp;
165
166
    if (_edge_filter_property == property)
        SetEdgeFilterProperty("",true);
167
168
}

Tiago Peixoto's avatar
Tiago Peixoto committed
169
170
171
172
173
void GraphInterface::RemoveGraphProperty(string property)
{
    dynamic_properties_copy dp;
    try
    {
174
175
        dynamic_property_map& prop_map =
            find_property_map(_properties, property,
176
                              typeid(graph_property_tag));
177
        for (typeof(_properties.begin()) iter = _properties.begin();
178
             iter != _properties.end(); ++iter)
Tiago Peixoto's avatar
Tiago Peixoto committed
179
180
        {
            if (iter->second != &prop_map)
181
                dp.insert(iter->first,
182
                          auto_ptr<dynamic_property_map>(iter->second));
Tiago Peixoto's avatar
Tiago Peixoto committed
183
184
185
186
187
188
189
190
191
192
        }
    }
    catch (property_not_found)
    {
        throw GraphException("property '" + property + "' not found");
    }
    _properties = dp;
}


193
struct add_property_map
194
{
195
196
197
198
    template <class ValueType, class IndexMap>
    void operator()(ValueType, const string& type_name, IndexMap index,
                    const string& property_name, dynamic_properties& dp,
                    bool& found) const
199
    {
200
201
        size_t i = mpl::find<value_types,ValueType>::type::pos::value;
        if (type_name == type_names[i])
202
        {
203
204
205
            vector_property_map<ValueType, IndexMap> prop(index);
            dp.property(property_name, prop);
            found = true;
206
        }
207
    }
208
209
};

210
void GraphInterface::AddVertexProperty(string property, string type)
211
{
212
    try
Tiago Peixoto's avatar
Tiago Peixoto committed
213
    {
214
215
216
        find_property_map(_properties, property, typeid(vertex_t));
        throw GraphException("A vertex property named " + property +
                             " already exists");
217
    }
218
219
    catch (PropertyNotFound){}

220
221
222
223
224
    bool found = false;
    mpl::for_each<value_types>(lambda::bind<void>(add_property_map(),
                                                  lambda::_1, lambda::var(type),
                                                  _vertex_index,
                                                  lambda::var(property),
225
                                                  lambda::var(_properties),
226
227
228
                                                  lambda::var(found)));
    if (!found)
        throw GraphException("Invalid property type " + type);
229
230
}

231
void GraphInterface::AddEdgeProperty(string property, string type)
232
{
233
234
235
236
237
238
    try
    {
        find_property_map(_properties, property, typeid(edge_t));
        throw GraphException("An edge property named " + property +
                             " already exists");
    }
239
240
    catch (PropertyNotFound) {}

241
    bool found = false;
242
    mpl::for_each<value_types>(lambda::bind<void>(add_property_map(),
243
                                                  lambda::_1, lambda::var(type),
244
                                                  _edge_index,
245
246
247
248
249
                                                  lambda::var(property),
                                                  lambda::var(_properties),
                                                  lambda::var(found)));
    if (!found)
        throw GraphException("Invalid property type " + type);
250
251
}

252
void GraphInterface::AddGraphProperty(string property, string type)
Tiago Peixoto's avatar
Tiago Peixoto committed
253
254
{
    ConstantPropertyMap<size_t,graph_property_tag> graph_index(0);
255
    try
256
    {
257
258
259
260
        find_property_map(_properties, property, typeid(graph_property_tag));
        throw GraphException("A graph property named " + property +
                             " already exists");
    }
261
262
    catch (PropertyNotFound){}

263
    bool found = false;
264
    mpl::for_each<value_types>(lambda::bind<void>(add_property_map(),
265
                                                  lambda::_1, lambda::var(type),
266
                                                  graph_index,
267
268
269
270
271
                                                  lambda::var(property),
                                                  lambda::var(_properties),
                                                  lambda::var(found)));
    if (!found)
        throw GraphException("Invalid property type " + type);
Tiago Peixoto's avatar
Tiago Peixoto committed
272
273
}

274
275
276
277
void GraphInterface::InsertEdgeIndexProperty(string property)
{
    _properties.property(property, _edge_index);
}
278

279
280
281
282
void GraphInterface::InsertVertexIndexProperty(string property)
{
    _properties.property(property, _vertex_index);
}
283

284
} // graph_tool namespace