igraph 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Manifest.txt ADDED
@@ -0,0 +1,24 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ ext/cIGraph.c
6
+ ext/cIGraph.h
7
+ ext/cIGraph_add_delete.c
8
+ ext/cIGraph_basic_properties.c
9
+ ext/cIGraph_basic_query.c
10
+ ext/cIGraph_error_handlers.c
11
+ ext/cIGraph_iterators.c
12
+ ext/cIGraph_operators.c
13
+ ext/cIGraph_selectors.c
14
+ ext/cIGraph_shortest_paths.c
15
+ ext/cIGraph_utility.c
16
+ test/tc_add_delete.rb
17
+ test/tc_basic_properties.rb
18
+ test/tc_basic_query.rb
19
+ test/tc_create.rb
20
+ test/tc_error_handling.rb
21
+ test/tc_iterators.rb
22
+ test/tc_selectors.rb
23
+ test/tc_shortest_paths.rb
24
+ test/test_all.rb
data/README.txt ADDED
@@ -0,0 +1,47 @@
1
+ == Introduction
2
+
3
+ IGraph
4
+
5
+ IGraph
6
+
7
+ IGraph
8
+
9
+ == Installation
10
+
11
+ A working igraph library installation is required.
12
+
13
+ An IGraph gem is available as well as a package using setup.rb. In each case the installation requires the location of your igraph library to compile the extension. If you download the setup.rb package use these incantations:
14
+
15
+ ruby setup.rb config -- --with-igraph-dir=$R_HOME
16
+ ruby setup.rb setup
17
+ ruby setup.rb install
18
+
19
+ Using gems it is almost the same:
20
+
21
+ gem install igraph -- --with-igraph-dir=$R_HOME
22
+
23
+ == Documentation
24
+
25
+ Here is a very quick and simple example:
26
+
27
+ require 'igraph'
28
+
29
+ graph = IGraph.new([],true)
30
+
31
+ == License
32
+
33
+ Copyright (C) 2006 Alex Gutteridge
34
+
35
+ This library is free software; you can redistribute it and/or
36
+ modify it under the terms of the GNU Lesser General Public
37
+ License as published by the Free Software Foundation; either
38
+ version 2.1 of the License, or (at your option) any later version.
39
+
40
+ This library is distributed in the hope that it will be useful,
41
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
42
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
43
+ Lesser General Public License for more details.
44
+
45
+ You should have received a copy of the GNU Lesser General Public
46
+ License along with this library; if not, write to the Free Software
47
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
data/ext/cIGraph.c ADDED
@@ -0,0 +1,160 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ void cIGraph_free(void *p){
6
+ igraph_destroy(p);
7
+ }
8
+
9
+ VALUE cIGraph_alloc(VALUE klass){
10
+
11
+ igraph_t *graph = malloc(sizeof(igraph_t));
12
+ VALUE obj;
13
+
14
+ igraph_empty(graph, 0, 1);
15
+ obj = Data_Wrap_Struct(klass, 0, cIGraph_free, graph);
16
+
17
+ return obj;
18
+
19
+ }
20
+
21
+ /* call-seq:
22
+ * IGraph.new(edges,directed) -> IGraph
23
+ *
24
+ * Creates a new IGraph graph with the edges specified in the edges Array.
25
+ * The first two elements define the first edge (the order is from,to for
26
+ * directed graphs). The next two define the second edge and so on. The
27
+ * Array should contain an even number of elements. Graph elements can be
28
+ * any ruby object.
29
+ *
30
+ * The boolean value directed specifies whether a directed or undirected
31
+ * graph is created.
32
+ *
33
+ * Example:
34
+ *
35
+ * IGraph.new([1,2,3,4],true)
36
+ *
37
+ * Creates a graph with four vertices. Vertex 1 is connected to vertex 2.
38
+ * Vertex 3 is connected to vertex 4.
39
+ */
40
+
41
+ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){
42
+
43
+ igraph_t *graph;
44
+ igraph_vector_t edge_v;
45
+ VALUE vertex;
46
+ VALUE object_h;
47
+ VALUE id_h;
48
+ int vertex_n = 0;
49
+ int current_vertex_id;
50
+
51
+ igraph_set_error_handler(cIGraph_error_handler);
52
+ igraph_set_warning_handler(cIGraph_warning_handler);
53
+
54
+ //New hash for mapping vertex objects to floats used by iGraph
55
+ object_h = rb_iv_set(self,"@object_ids",rb_hash_new());
56
+ id_h = rb_iv_set(self,"@id_objects",rb_hash_new());
57
+
58
+ //Initialize edge vector
59
+ igraph_vector_init_int(&edge_v,0);
60
+
61
+ Data_Get_Struct(self, igraph_t, graph);
62
+ if(!directed)
63
+ igraph_to_undirected(graph,IGRAPH_TO_UNDIRECTED_COLLAPSE);
64
+
65
+ //Loop through objects in edge Array
66
+ vertex = rb_ary_shift(edges);
67
+ while(vertex != Qnil){
68
+ if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){
69
+ //If @vertices includes this vertex then look up the vertex number
70
+ current_vertex_id = NUM2INT(rb_hash_aref(object_h,vertex));
71
+ } else {
72
+ //otherwise add a new entry to Hash
73
+ rb_hash_aset(object_h,vertex,INT2NUM(vertex_n));
74
+ rb_hash_aset(id_h, INT2NUM(vertex_n),vertex);
75
+ current_vertex_id = vertex_n;
76
+ vertex_n++;
77
+ }
78
+ igraph_vector_push_back(&edge_v,current_vertex_id);
79
+ vertex = rb_ary_shift(edges);
80
+ }
81
+
82
+ if(igraph_vector_size(&edge_v) > 0){
83
+ igraph_add_vertices(graph,vertex_n,0);
84
+ igraph_add_edges(graph,&edge_v,0);
85
+ }
86
+
87
+ igraph_vector_destroy(&edge_v);
88
+
89
+ return self;
90
+
91
+ }
92
+
93
+ /* Interface to the iGraph[http://cneurocvs.rmki.kfki.hu/igraph/] library
94
+ * for graph and network computation. See IGraph#new for how to create a
95
+ * graph and get started.
96
+ */
97
+
98
+ void Init_igraph(){
99
+ cIGraph = rb_define_class("IGraph", rb_cObject);
100
+ cIGraphError = rb_define_class("IGraphError", rb_eRuntimeError);
101
+
102
+ rb_define_alloc_func(cIGraph, cIGraph_alloc);
103
+ rb_define_method(cIGraph, "initialize", cIGraph_initialize, 2);
104
+
105
+ rb_define_method(cIGraph, "each_vertex", cIGraph_each_vertex, 0); /* in cIGraph_iterators.c */
106
+ rb_define_method(cIGraph, "each_edge", cIGraph_each_edge, 1); /* in cIGraph_iterators.c */
107
+ rb_define_method(cIGraph, "each_edge_eid", cIGraph_each_edge_eid,1); /* in cIGraph_iterators.c */
108
+
109
+ rb_define_const(cIGraph, "EDGEORDER_ID", INT2NUM(1));
110
+ rb_define_const(cIGraph, "EDGEORDER_FROM", INT2NUM(2));
111
+ rb_define_const(cIGraph, "EDGEORDER_TO", INT2NUM(3));
112
+
113
+ rb_define_method(cIGraph, "each", cIGraph_each_vertex, 0);
114
+ rb_include_module(cIGraph, rb_mEnumerable);
115
+
116
+ rb_define_method(cIGraph, "include?", cIGraph_include, 1);
117
+
118
+ rb_define_method(cIGraph, "all_vertices", cIGraph_all_v, 0);
119
+ rb_define_method(cIGraph, "vertices", cIGraph_all_v, 0); /* in cIGraph_selectors.c */
120
+ rb_define_method(cIGraph, "adjacent_vertices", cIGraph_adj_v, 2); /* in cIGraph_selectors.c */
121
+ rb_define_method(cIGraph, "nonadjacent_vertices", cIGraph_nonadj_v, 2); /* in cIGraph_selectors.c */
122
+
123
+ rb_define_method(cIGraph, "all_edges", cIGraph_all_e, 1);
124
+ rb_define_method(cIGraph, "edges", cIGraph_all_e, 1);
125
+ rb_define_method(cIGraph, "adjacent_edges", cIGraph_adj_e, 2);
126
+ rb_define_method(cIGraph, "nonadjacent_edges", cIGraph_nonadj_e, 2);
127
+
128
+ rb_define_method(cIGraph, "vcount", cIGraph_vcount, 0); /* in cIGraph_basic_query.c */
129
+ rb_define_method(cIGraph, "ecount", cIGraph_ecount, 0); /* in cIGraph_basic_query.c */
130
+
131
+ rb_define_method(cIGraph, "edge", cIGraph_edge, 1); /* in cIGraph_basic_query.c */
132
+ rb_define_method(cIGraph, "get_eid", cIGraph_get_eid, 2); /* in cIGraph_basic_query.c */
133
+
134
+ rb_define_method(cIGraph, "neighbors", cIGraph_neighbors,2);
135
+ rb_define_method(cIGraph, "neighbours", cIGraph_neighbors,2); /* in cIGraph_basic_query.c */
136
+ rb_define_method(cIGraph, "adjacent", cIGraph_adjacent,2); /* in cIGraph_basic_query.c */
137
+
138
+ rb_define_const(cIGraph, "OUT", INT2NUM(1));
139
+ rb_define_const(cIGraph, "IN", INT2NUM(2));
140
+ rb_define_const(cIGraph, "ALL", INT2NUM(3));
141
+ rb_define_const(cIGraph, "TOTAL", INT2NUM(4));
142
+
143
+ rb_define_method(cIGraph, "is_directed", cIGraph_is_directed,0);
144
+ rb_define_method(cIGraph, "is_directed?", cIGraph_is_directed,0); /* in cIGraph_basic_query.c */
145
+
146
+ rb_define_method(cIGraph, "degree", cIGraph_degree,3); /* in cIGraph_basic_query.c */
147
+
148
+ rb_define_method(cIGraph, "add_edges", cIGraph_add_edges, 1); /* in cIGraph_add_delete.c */
149
+ rb_define_method(cIGraph, "add_vertices", cIGraph_add_vertices, 1); /* in cIGraph_add_delete.c */
150
+
151
+ rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, 2); /* in cIGraph_add_delete.c */
152
+ rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); /* in cIGraph_add_delete.c */
153
+
154
+ rb_define_method(cIGraph, "are_connected", cIGraph_are_connected,2);
155
+ rb_define_method(cIGraph, "are_connected?", cIGraph_are_connected,2); /* in cIGraph_basic_properties.c */
156
+
157
+ rb_define_method(cIGraph, "shortest_paths", cIGraph_shortest_paths,2);
158
+ rb_define_method(cIGraph, "get_shortest_paths", cIGraph_get_shortest_paths,3);
159
+
160
+ }
data/ext/cIGraph.h ADDED
@@ -0,0 +1,60 @@
1
+ //Classes
2
+ VALUE cIGraph;
3
+ VALUE cIGraphError;
4
+
5
+ //Error and warning handling functions
6
+ void cIGraph_error_handler(const char *reason, const char *file,
7
+ int line, int igraph_errno);
8
+ void cIGraph_warning_handler(const char *reason, const char *file,
9
+ int line, int igraph_errno);
10
+
11
+ //IGraph specific utility functions
12
+ igraph_integer_t cIGraph_get_vertex_id(VALUE graph, VALUE v);
13
+ VALUE cIGraph_get_vertex_object(VALUE graph, igraph_integer_t n);
14
+ int cIGraph_vertex_arr_to_id_vec(VALUE graph, VALUE va, igraph_vector_t *nv);
15
+ VALUE cIGraph_include(VALUE self, VALUE v);
16
+
17
+ //IGraph allocation, destruction and intialization
18
+ void Init_igraph(void);
19
+ void cIGraph_free(void *p);
20
+ VALUE cIGraph_alloc(VALUE klass);
21
+ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed);
22
+
23
+ //Iterators
24
+ VALUE cIGraph_each_vertex (VALUE self);
25
+ VALUE cIGraph_each_edge (VALUE self, VALUE order);
26
+ VALUE cIGraph_each_edge_eid(VALUE self, VALUE order);
27
+
28
+ //Selectors
29
+ VALUE cIGraph_all_v (VALUE self);
30
+ VALUE cIGraph_adj_v (VALUE self, VALUE v, VALUE mode);
31
+ VALUE cIGraph_nonadj_v(VALUE self, VALUE v, VALUE mode);
32
+
33
+ VALUE cIGraph_all_e (VALUE self, VALUE mode);
34
+ VALUE cIGraph_adj_e (VALUE self, VALUE v, VALUE mode);
35
+ VALUE cIGraph_nonadj_e(VALUE self, VALUE v, VALUE mode);
36
+
37
+ //Basic query operations
38
+ VALUE cIGraph_vcount (VALUE self);
39
+ VALUE cIGraph_ecount (VALUE self);
40
+ VALUE cIGraph_edge (VALUE self, VALUE eid);
41
+ VALUE cIGraph_get_eid (VALUE self, VALUE from, VALUE to, VALUE directed);
42
+ VALUE cIGraph_neighbors (VALUE self, VALUE v, VALUE mode);
43
+ VALUE cIGraph_adjacent (VALUE self, VALUE v, VALUE mode);
44
+ VALUE cIGraph_is_directed(VALUE self);
45
+ VALUE cIGraph_degree (VALUE self, VALUE v, VALUE mode, VALUE loops);
46
+
47
+ //Adding and eleting vertices and edges
48
+ VALUE cIGraph_add_edges (VALUE self, VALUE edges);
49
+ VALUE cIGraph_add_vertices (VALUE self, VALUE vs);
50
+ VALUE cIGraph_delete_edges (VALUE self, VALUE edges);
51
+ VALUE cIGraph_delete_vertices(VALUE self, VALUE vs);
52
+ VALUE cIGraph_add_edge (VALUE self, VALUE from, VALUE to);
53
+ VALUE cIGraph_add_vertex (VALUE self, VALUE v);
54
+
55
+ //Basic properties
56
+ VALUE cIGraph_are_connected(VALUE self, VALUE from, VALUE to);
57
+
58
+ //Shortest Path Related Functions
59
+ VALUE cIGraph_shortest_paths (VALUE self, VALUE from, VALUE mode);
60
+ VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode);
@@ -0,0 +1,219 @@
1
+ #include "igraph.h"
2
+ #include "ruby.h"
3
+ #include "cIGraph.h"
4
+
5
+ /* call-seq:
6
+ * graph.add_edges(edges) -> Fixnum
7
+ *
8
+ * Adds the edges in the edges Array to the graph. Edges are specified as an
9
+ * Array in the same way as with IGraph#new.
10
+ *
11
+ * Returns 0 on success.
12
+ *
13
+ * Example:
14
+ *
15
+ * g = IGraph.new([1,2,3,4],true)
16
+ * g.add_edges([1,4,2,3])
17
+ *
18
+ * Adds an extra directed edge to this trivial graph. Note that vertices
19
+ * must have already been added to the graph before they can be used in
20
+ * an edge (throws a IGraphError otherwise).
21
+ */
22
+ VALUE cIGraph_add_edges(VALUE self, VALUE edges){
23
+
24
+ igraph_t *graph;
25
+ igraph_vector_t edge_v;
26
+ VALUE vertex;
27
+ VALUE object_h;
28
+ int vid;
29
+ int code = 0;
30
+
31
+ //Initialize edge vector
32
+ igraph_vector_init_int(&edge_v,0);
33
+ object_h = rb_iv_get(self,"@object_ids");
34
+
35
+ Data_Get_Struct(self, igraph_t, graph);
36
+
37
+ //Loop through objects in edge Array
38
+ vertex = rb_ary_shift(edges);
39
+ while(vertex != Qnil){
40
+ if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){
41
+ //If @vertices includes this vertex then look up the vertex number
42
+ vid = NUM2INT(rb_hash_aref(object_h,vertex));
43
+ } else {
44
+ rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first");
45
+ }
46
+ igraph_vector_push_back(&edge_v,vid);
47
+ vertex = rb_ary_shift(edges);
48
+ }
49
+
50
+ if(igraph_vector_size(&edge_v) > 0){
51
+ code = igraph_add_edges(graph,&edge_v,0);
52
+ }
53
+
54
+ igraph_vector_destroy(&edge_v);
55
+
56
+ return INT2NUM(code);
57
+
58
+ }
59
+
60
+ /* call-seq:
61
+ * graph.add_vertices(vs) -> Fixnum
62
+ *
63
+ * Adds the vertices in the vs Array to the graph.
64
+ *
65
+ * Returns 0 on success.
66
+ *
67
+ * Example:
68
+ *
69
+ * g = IGraph.new([1,2,3,4],true)
70
+ * g.add_vertices([5,6,7,8])
71
+ *
72
+ * Adds 4 extra vertices to this graph. IGraph will silently ignore attempts
73
+ * to add a vertex twice to the same graph.
74
+ */
75
+ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){
76
+
77
+ igraph_t *graph;
78
+ VALUE vertex;
79
+ VALUE object_h;
80
+ VALUE id_h;
81
+ int vertex_n;
82
+ int code = 0;
83
+ int length;
84
+
85
+ object_h = rb_iv_get(self,"@object_ids");
86
+ id_h = rb_iv_get(self,"@id_objects");
87
+ length = NUM2INT(rb_funcall(vs, rb_intern("length"),0));
88
+ vertex_n = NUM2INT(rb_funcall(object_h,rb_intern("length"),0));
89
+
90
+ Data_Get_Struct(self, igraph_t, graph);
91
+
92
+ //Loop through objects in vertex array
93
+ vertex = rb_ary_shift(vs);
94
+ while(vertex != Qnil){
95
+ if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){
96
+ //If @vertices includes this vertex then raise an error
97
+ //Silently ignore
98
+ //rb_raise(cIGraphError, "Vertex already added to graph");
99
+ length--;
100
+ } else {
101
+ //otherwise add a new entry to Hash
102
+ rb_hash_aset(object_h,vertex,INT2NUM(vertex_n));
103
+ rb_hash_aset(id_h, INT2NUM(vertex_n),vertex);
104
+ vertex_n++;
105
+ }
106
+ vertex = rb_ary_shift(vs);
107
+ }
108
+ code = igraph_add_vertices(graph,length,0);
109
+
110
+ return INT2NUM(code);
111
+
112
+ }
113
+
114
+ /* call-seq:
115
+ * graph.add_edge(from,to) -> Fixnum
116
+ *
117
+ * Adds an edge between the two vertices given. This is just a convinience
118
+ * method, it is possible to use IGraph#add_edges to add a single edge as well
119
+ *
120
+ * Returns 0 on success.
121
+ *
122
+ * Example:
123
+ *
124
+ * g = IGraph.new([1,2,3,4],true)
125
+ * g.add_edge(1,4)
126
+ *
127
+ * Note that vertices must have already been added to the graph before
128
+ * they can be used in an edge (throws a IGraphError otherwise).
129
+ */
130
+ VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){
131
+
132
+ igraph_t *graph;
133
+ igraph_vector_t edge_v;
134
+ VALUE object_h;
135
+ int vid;
136
+ int code = 0;
137
+
138
+ //Initialize edge vector
139
+ igraph_vector_init_int(&edge_v,0);
140
+ object_h = rb_iv_get(self,"@object_ids");
141
+
142
+ Data_Get_Struct(self, igraph_t, graph);
143
+
144
+ if(rb_funcall(object_h,rb_intern("has_key?"),1,from)){
145
+ //If @vertices includes this vertex then look up the vertex number
146
+ vid = NUM2INT(rb_hash_aref(object_h,from));
147
+ } else {
148
+ rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first");
149
+ }
150
+ igraph_vector_push_back(&edge_v,vid);
151
+
152
+ if(rb_funcall(object_h,rb_intern("has_key?"),1,to)){
153
+ //If @vertices includes this vertex then look up the vertex number
154
+ vid = NUM2INT(rb_hash_aref(object_h,to));
155
+ } else {
156
+ rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first");
157
+ }
158
+ igraph_vector_push_back(&edge_v,vid);
159
+
160
+ code = igraph_add_edges(graph,&edge_v,0);
161
+
162
+ igraph_vector_destroy(&edge_v);
163
+
164
+ return INT2NUM(code);
165
+
166
+ }
167
+
168
+ /* call-seq:
169
+ * graph.add_vertex(v) -> Fixnum
170
+ *
171
+ * Adds the vertex to the graph. This is just a convinience method it is
172
+ * also possible to use IGraph#add_vertices to add a single vertex.
173
+ *
174
+ * Returns 0 on success.
175
+ *
176
+ * Example:
177
+ *
178
+ * g = IGraph.new([1,2,3,4],true)
179
+ * g.add_vertex(5)
180
+ *
181
+ * Adds 1 extra vertex to this graph. IGraph will silently ignore attempts
182
+ * to add a vertex twice to the same graph.
183
+ */
184
+ VALUE cIGraph_add_vertex(VALUE self, VALUE v){
185
+
186
+ igraph_t *graph;
187
+ VALUE vertex;
188
+ VALUE object_h;
189
+ VALUE id_h;
190
+ int vertex_n;
191
+ int code = 0;
192
+ int length;
193
+
194
+ object_h = rb_iv_get(self,"@object_ids");
195
+ id_h = rb_iv_get(self,"@id_objects");
196
+ length = 1;
197
+ vertex_n = NUM2INT(rb_funcall(object_h,rb_intern("length"),0));
198
+
199
+ Data_Get_Struct(self, igraph_t, graph);
200
+
201
+ //Loop through objects in vertex array
202
+ if(rb_funcall(object_h,rb_intern("has_key?"),1,v)){
203
+ //If @vertices includes this vertex then raise an error
204
+ //Silently ignore
205
+ //rb_raise(cIGraphError, "Vertex already added to graph");
206
+ length--;
207
+ } else {
208
+ //otherwise add a new entry to Hash
209
+ rb_hash_aset(object_h,v,INT2NUM(vertex_n));
210
+ rb_hash_aset(id_h, INT2NUM(vertex_n),v);
211
+ vertex_n++;
212
+ }
213
+
214
+ if(length != 0)
215
+ code = igraph_add_vertices(graph,length,0);
216
+
217
+ return INT2NUM(code);
218
+
219
+ }