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/History.txt +3 -0
- data/License.txt +504 -0
- data/Manifest.txt +24 -0
- data/README.txt +47 -0
- data/ext/cIGraph.c +160 -0
- data/ext/cIGraph.h +60 -0
- data/ext/cIGraph_add_delete.c +219 -0
- data/ext/cIGraph_basic_properties.c +34 -0
- data/ext/cIGraph_basic_query.c +260 -0
- data/ext/cIGraph_error_handlers.c +13 -0
- data/ext/cIGraph_iterators.c +135 -0
- data/ext/cIGraph_operators.c +9 -0
- data/ext/cIGraph_selectors.c +93 -0
- data/ext/cIGraph_shortest_paths.c +112 -0
- data/ext/cIGraph_utility.c +56 -0
- data/ext/extconf.rb +12 -0
- data/test/tc_add_delete.rb +49 -0
- data/test/tc_basic_properties.rb +10 -0
- data/test/tc_basic_query.rb +54 -0
- data/test/tc_create.rb +11 -0
- data/test/tc_error_handling.rb +10 -0
- data/test/tc_iterators.rb +44 -0
- data/test/tc_selectors.rb +14 -0
- data/test/tc_shortest_paths.rb +21 -0
- data/test/test_all.rb +12 -0
- metadata +75 -0
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
|
+
}
|