igraph 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,93 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
/* call-seq:
|
6
|
+
* graph.vertices -> Array
|
7
|
+
*
|
8
|
+
* Returns an Array containing all the vertices in the graph. Also aliased
|
9
|
+
* to IGraph#all_vertices
|
10
|
+
*
|
11
|
+
* Example:
|
12
|
+
*
|
13
|
+
* g = IGraph.new([1,2,3,4],true)
|
14
|
+
* g.vertices #returns [1,2,3,4]
|
15
|
+
*
|
16
|
+
*/
|
17
|
+
VALUE cIGraph_all_v(VALUE self){
|
18
|
+
igraph_t *graph;
|
19
|
+
|
20
|
+
Data_Get_Struct(self, igraph_t, graph);
|
21
|
+
return rb_funcall(rb_iv_get(self,"@object_ids"),rb_intern("keys"),0);
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
/* call-seq:
|
26
|
+
* graph.adjacent_vertices(v,mode) -> Array
|
27
|
+
*
|
28
|
+
* Returns an Array containing all the vertices in the graph that are
|
29
|
+
* adjacent to vertex v. mode decides the type of the neighborhood for
|
30
|
+
* directed graphs. Possible values: IGRAPH_OUT, all vertices to which
|
31
|
+
* there is a directed edge from vid. IGRAPH_IN, all vertices from which
|
32
|
+
* there is a directed edge from vid. IGRAPH_ALL, all vertices to which
|
33
|
+
* or from which there is a directed edge from/to vid. This parameter is
|
34
|
+
* ignored for undirected graphs.
|
35
|
+
*
|
36
|
+
* Example:
|
37
|
+
*
|
38
|
+
* g = IGraph.new([1,2,3,4],true)
|
39
|
+
* g.adjacent_vertices(1,IGraph::ALL) #returns [2]
|
40
|
+
*
|
41
|
+
*/
|
42
|
+
VALUE cIGraph_adj_v(VALUE self, VALUE v, VALUE mode){
|
43
|
+
|
44
|
+
igraph_t *graph;
|
45
|
+
igraph_integer_t pnode;
|
46
|
+
VALUE adjacent = rb_ary_new();
|
47
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
48
|
+
igraph_vs_t vs;
|
49
|
+
igraph_vit_t vit;
|
50
|
+
|
51
|
+
Data_Get_Struct(self, igraph_t, graph);
|
52
|
+
|
53
|
+
pnode = cIGraph_get_vertex_id(self,v);
|
54
|
+
|
55
|
+
igraph_vs_adj(&vs,pnode,pmode);
|
56
|
+
igraph_vit_create(graph, vs, &vit);
|
57
|
+
|
58
|
+
while(!IGRAPH_VIT_END(vit)) {
|
59
|
+
rb_ary_push(adjacent,cIGraph_get_vertex_object(self,IGRAPH_VIT_GET(vit)));
|
60
|
+
IGRAPH_VIT_NEXT(vit);
|
61
|
+
}
|
62
|
+
|
63
|
+
igraph_vit_destroy(&vit);
|
64
|
+
igraph_vs_destroy(&vs);
|
65
|
+
|
66
|
+
return adjacent;
|
67
|
+
|
68
|
+
}
|
69
|
+
|
70
|
+
VALUE cIGraph_nonadj_v(VALUE self, VALUE v, VALUE mode){
|
71
|
+
|
72
|
+
return Qnil;
|
73
|
+
|
74
|
+
}
|
75
|
+
|
76
|
+
VALUE cIGraph_all_e(VALUE self, VALUE mode){
|
77
|
+
|
78
|
+
return Qnil;
|
79
|
+
|
80
|
+
}
|
81
|
+
|
82
|
+
VALUE cIGraph_adj_e(VALUE self, VALUE v, VALUE mode){
|
83
|
+
|
84
|
+
return Qnil;
|
85
|
+
|
86
|
+
}
|
87
|
+
|
88
|
+
VALUE cIGraph_nonadj_e(VALUE self, VALUE v, VALUE mode){
|
89
|
+
|
90
|
+
return Qnil;
|
91
|
+
|
92
|
+
}
|
93
|
+
|
@@ -0,0 +1,112 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){
|
6
|
+
|
7
|
+
igraph_t *graph;
|
8
|
+
igraph_vs_t vids;
|
9
|
+
igraph_vector_t vidv;
|
10
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
11
|
+
igraph_matrix_t res;
|
12
|
+
int i;
|
13
|
+
int j;
|
14
|
+
VALUE row;
|
15
|
+
VALUE path_length;
|
16
|
+
VALUE matrix = rb_ary_new();
|
17
|
+
int n_row;
|
18
|
+
int n_col;
|
19
|
+
|
20
|
+
Data_Get_Struct(self, igraph_t, graph);
|
21
|
+
|
22
|
+
n_row = NUM2INT(rb_funcall(from,rb_intern("length"),0));
|
23
|
+
n_col = igraph_vcount(graph);
|
24
|
+
|
25
|
+
//matrix to hold the results of the calculations
|
26
|
+
igraph_matrix_init(&res,n_row,n_col);
|
27
|
+
|
28
|
+
//Convert an array of vertices to a vector of vertex ids
|
29
|
+
cIGraph_vertex_arr_to_id_vec(self,from,&vidv);
|
30
|
+
//create vertex selector from the vecotr of ids
|
31
|
+
igraph_vs_vector(&vids,&vidv);
|
32
|
+
|
33
|
+
igraph_shortest_paths(graph,&res,vids,pmode);
|
34
|
+
|
35
|
+
for(i=0; i<igraph_matrix_nrow(&res); i++){
|
36
|
+
row = rb_ary_new();
|
37
|
+
rb_ary_push(matrix,row);
|
38
|
+
for(j=0; j<igraph_matrix_ncol(&res); j++){
|
39
|
+
path_length = MATRIX(res,i,j) == n_col ? Qnil : INT2NUM(MATRIX(res,i,j));
|
40
|
+
rb_ary_push(row,path_length);
|
41
|
+
}
|
42
|
+
}
|
43
|
+
|
44
|
+
igraph_vector_destroy(&vidv);
|
45
|
+
igraph_matrix_destroy(&res);
|
46
|
+
igraph_vs_destroy(&vids);
|
47
|
+
|
48
|
+
return matrix;
|
49
|
+
|
50
|
+
}
|
51
|
+
|
52
|
+
VALUE cIGraph_get_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){
|
53
|
+
|
54
|
+
igraph_t *graph;
|
55
|
+
|
56
|
+
igraph_integer_t from_vid;
|
57
|
+
igraph_vs_t to_vids;
|
58
|
+
igraph_vector_t to_vidv;
|
59
|
+
|
60
|
+
igraph_neimode_t pmode = NUM2INT(mode);
|
61
|
+
|
62
|
+
igraph_vector_ptr_t res;
|
63
|
+
igraph_vector_t *path_v;
|
64
|
+
|
65
|
+
int i;
|
66
|
+
int j;
|
67
|
+
VALUE path;
|
68
|
+
VALUE matrix = rb_ary_new();
|
69
|
+
int n_paths;
|
70
|
+
|
71
|
+
Data_Get_Struct(self, igraph_t, graph);
|
72
|
+
|
73
|
+
n_paths = NUM2INT(rb_funcall(to,rb_intern("length"),0));
|
74
|
+
|
75
|
+
//vector to hold the results of the calculations
|
76
|
+
igraph_vector_ptr_init(&res,0);
|
77
|
+
for(i=0;i<n_paths;i++){
|
78
|
+
path_v = malloc(sizeof(igraph_vector_t));
|
79
|
+
igraph_vector_init(path_v,0);
|
80
|
+
igraph_vector_ptr_push_back(&res,path_v);
|
81
|
+
}
|
82
|
+
|
83
|
+
//Convert an array of vertices to a vector of vertex ids
|
84
|
+
cIGraph_vertex_arr_to_id_vec(self,to,&to_vidv);
|
85
|
+
//create vertex selector from the vecotr of ids
|
86
|
+
igraph_vs_vector(&to_vids,&to_vidv);
|
87
|
+
|
88
|
+
//The id of the vertex from where we are counting
|
89
|
+
from_vid = cIGraph_get_vertex_id(self, from);
|
90
|
+
|
91
|
+
igraph_get_shortest_paths(graph,&res,from_vid,to_vids,pmode);
|
92
|
+
|
93
|
+
for(i=0; i<n_paths; i++){
|
94
|
+
path = rb_ary_new();
|
95
|
+
rb_ary_push(matrix,path);
|
96
|
+
for(j=0; j<igraph_vector_size(VECTOR(res)[i]); j++){
|
97
|
+
path_v = VECTOR(res)[i];
|
98
|
+
rb_ary_push(path,cIGraph_get_vertex_object(self,VECTOR(*path_v)[j]));
|
99
|
+
}
|
100
|
+
}
|
101
|
+
|
102
|
+
for(i=0;i<n_paths;i++){
|
103
|
+
igraph_vector_destroy(VECTOR(res)[i]);
|
104
|
+
}
|
105
|
+
|
106
|
+
igraph_vector_destroy(&to_vidv);
|
107
|
+
igraph_vector_ptr_destroy(&res);
|
108
|
+
igraph_vs_destroy(&to_vids);
|
109
|
+
|
110
|
+
return matrix;
|
111
|
+
|
112
|
+
}
|
@@ -0,0 +1,56 @@
|
|
1
|
+
#include "igraph.h"
|
2
|
+
#include "ruby.h"
|
3
|
+
#include "cIGraph.h"
|
4
|
+
|
5
|
+
igraph_integer_t cIGraph_get_vertex_id(VALUE graph, VALUE v){
|
6
|
+
|
7
|
+
VALUE vertex_h;
|
8
|
+
|
9
|
+
vertex_h = rb_iv_get(graph,"@object_ids");
|
10
|
+
|
11
|
+
if(rb_funcall(vertex_h,rb_intern("has_key?"),1,v))
|
12
|
+
return NUM2INT(rb_hash_aref(vertex_h,v));
|
13
|
+
|
14
|
+
return -1;
|
15
|
+
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE cIGraph_get_vertex_object(VALUE graph, igraph_integer_t n){
|
19
|
+
|
20
|
+
VALUE vertex_h;
|
21
|
+
|
22
|
+
vertex_h = rb_iv_get(graph,"@id_objects");
|
23
|
+
|
24
|
+
if(rb_funcall(vertex_h,rb_intern("has_key?"),1,INT2NUM(n)))
|
25
|
+
return rb_hash_aref(vertex_h,INT2NUM(n));
|
26
|
+
|
27
|
+
return Qnil;
|
28
|
+
|
29
|
+
}
|
30
|
+
|
31
|
+
int cIGraph_vertex_arr_to_id_vec(VALUE graph, VALUE va, igraph_vector_t *nv){
|
32
|
+
|
33
|
+
VALUE vertex;
|
34
|
+
VALUE tmp;
|
35
|
+
|
36
|
+
tmp = rb_check_array_type(va);
|
37
|
+
|
38
|
+
if(NIL_P(tmp))
|
39
|
+
rb_raise(cIGraphError, "Array expected\n");
|
40
|
+
|
41
|
+
//Initialize edge vector
|
42
|
+
igraph_vector_init_int(nv,0);
|
43
|
+
vertex = rb_ary_shift(va);
|
44
|
+
while(vertex != Qnil){
|
45
|
+
igraph_vector_push_back(nv,cIGraph_get_vertex_id(graph, vertex));
|
46
|
+
vertex = rb_ary_shift(va);
|
47
|
+
}
|
48
|
+
|
49
|
+
return 0;
|
50
|
+
|
51
|
+
}
|
52
|
+
|
53
|
+
VALUE cIGraph_include(VALUE self, VALUE v){
|
54
|
+
VALUE vertex_h = rb_iv_get(self,"@object_ids");
|
55
|
+
return rb_funcall(vertex_h,rb_intern("has_key?"),1,v);
|
56
|
+
}
|
data/ext/extconf.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
dir_config('igraph')
|
3
|
+
unless have_library("igraph")
|
4
|
+
$stderr.puts "\nERROR: Cannot find the iGraph library, aborting."
|
5
|
+
exit 1
|
6
|
+
end
|
7
|
+
unless have_header("igraph.h")
|
8
|
+
$stderr.puts "\nERROR: Cannot find the iGraph header, aborting."
|
9
|
+
exit 1
|
10
|
+
end
|
11
|
+
|
12
|
+
create_makefile("igraph")
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'igraph'
|
3
|
+
|
4
|
+
class TestGraph < Test::Unit::TestCase
|
5
|
+
def test_add_edges
|
6
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
7
|
+
graph.add_edges(['A','C'])
|
8
|
+
assert_equal [2], graph.degree(['A'],IGraph::ALL,true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def test_add_vertices
|
12
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
13
|
+
assert_equal 4, graph.vcount
|
14
|
+
graph.add_vertices(['E','F','G','H'])
|
15
|
+
assert_equal 8, graph.vcount
|
16
|
+
assert_equal [0], graph.degree(['E'],IGraph::ALL,true)
|
17
|
+
assert_nothing_raised do
|
18
|
+
graph.add_vertices(['H','I'])
|
19
|
+
end
|
20
|
+
assert_equal 9, graph.vcount
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_add_to_empty_graph
|
24
|
+
graph = IGraph.new([],true)
|
25
|
+
assert_equal 0, graph.vcount
|
26
|
+
graph.add_vertices(['A','B'])
|
27
|
+
assert_equal 2, graph.vcount
|
28
|
+
graph.add_edges(['A','B'])
|
29
|
+
assert_equal 1, graph.ecount
|
30
|
+
end
|
31
|
+
|
32
|
+
def test_add_edge
|
33
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
34
|
+
assert_nothing_raised do
|
35
|
+
graph.add_edge('A','D')
|
36
|
+
end
|
37
|
+
assert_equal [2], graph.degree(['A'],IGraph::ALL,true)
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_add_vertex
|
41
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
42
|
+
assert_nothing_raised do
|
43
|
+
graph.add_vertex('E')
|
44
|
+
end
|
45
|
+
assert_equal 5, graph.vcount
|
46
|
+
assert_equal [0], graph.degree(['E'],IGraph::ALL,true)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'igraph'
|
3
|
+
|
4
|
+
class TestGraph < Test::Unit::TestCase
|
5
|
+
def test_graph_size
|
6
|
+
assert_equal 4, IGraph.new([1,2,3,4],true).vcount
|
7
|
+
assert_equal 2, IGraph.new([1,2,3,4],true).ecount
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_eid_get_edge
|
11
|
+
assert_nothing_raised do
|
12
|
+
IGraph.new(['A','B','C','D'],true).get_eid('A','B')
|
13
|
+
end
|
14
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
15
|
+
eid1 = graph.get_eid('A','B')
|
16
|
+
eid2 = graph.get_eid('C','D')
|
17
|
+
assert_equal ['A','B'], graph.edge(eid1)
|
18
|
+
assert_equal ['C','D'], graph.edge(eid2);
|
19
|
+
assert_not_equal eid1,eid2
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_neighbours
|
23
|
+
assert_nothing_raised do
|
24
|
+
IGraph.new(['A','B','C','D'],true).neighbors('A',IGraph::ALL)
|
25
|
+
end
|
26
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
27
|
+
assert_equal ['B'], graph.neighbors('A',IGraph::ALL)
|
28
|
+
assert_equal ['D'], graph.neighbors('C',IGraph::ALL)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_adjacent
|
32
|
+
assert_nothing_raised do
|
33
|
+
IGraph.new(['A','B','C','D'],true).adjacent('A',IGraph::ALL)
|
34
|
+
end
|
35
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
36
|
+
eid1 = graph.get_eid('A','B')
|
37
|
+
eid2 = graph.adjacent('A',IGraph::ALL)[0]
|
38
|
+
assert_equal eid1, eid2
|
39
|
+
end
|
40
|
+
|
41
|
+
def test_directed
|
42
|
+
assert IGraph.new(['A','B','C','D'],true).is_directed?
|
43
|
+
assert !(IGraph.new(['A','B','C','D'],false).is_directed?)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_degree
|
47
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
48
|
+
assert_equal [1], graph.degree(['A'], IGraph::ALL,true)
|
49
|
+
assert_equal [1,1],graph.degree(['A','B'],IGraph::ALL,true)
|
50
|
+
assert_raises IGraphError do
|
51
|
+
graph.degree('A',IGraph::ALL,true)
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/test/tc_create.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'igraph'
|
3
|
+
|
4
|
+
class TestGraph < Test::Unit::TestCase
|
5
|
+
def test_each_vertex
|
6
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
7
|
+
assert_nothing_raised do
|
8
|
+
graph.each_vertex do |v|
|
9
|
+
end
|
10
|
+
end
|
11
|
+
assert_nothing_raised do
|
12
|
+
graph.each do |v|
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_each_edge
|
18
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
19
|
+
assert_nothing_raised do
|
20
|
+
graph.each_edge(IGraph::EDGEORDER_ID) do |v,w|
|
21
|
+
end
|
22
|
+
end
|
23
|
+
assert_nothing_raised do
|
24
|
+
graph.each_edge_eid(IGraph::EDGEORDER_ID) do |v|
|
25
|
+
end
|
26
|
+
end
|
27
|
+
edges = []
|
28
|
+
graph.each_edge(IGraph::EDGEORDER_ID){|v,w| edges.push([v,w])}
|
29
|
+
assert_equal [['A','B'],['C','D']], edges
|
30
|
+
edges = []
|
31
|
+
graph.each_edge_eid(IGraph::EDGEORDER_ID){|v| edges.push(v)}
|
32
|
+
assert_equal [0,1], edges
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_enumerable
|
36
|
+
graph = IGraph.new(['A','B','C','D'],true)
|
37
|
+
assert graph.all?{|v| v.kind_of? String}
|
38
|
+
assert graph.any?{|v| v == 'B'}
|
39
|
+
assert_equal ['A','B','C','D'], graph.collect{|v| v}
|
40
|
+
assert graph.detect(Proc.new{true}){|v| }
|
41
|
+
assert_equal ['A'], graph.find_all{|v| v < 'B'}
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|