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
@@ -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
|