| @@ -8,6 +8,9 @@ ext/cIGraph_add_delete.c | |||||
| ext/cIGraph_basic_properties.c | ext/cIGraph_basic_properties.c | ||||
| ext/cIGraph_basic_query.c | ext/cIGraph_basic_query.c | ||||
| ext/cIGraph_error_handlers.c | ext/cIGraph_error_handlers.c | ||||
| ext/cIGraph_iterators.c | |||||
| ext/cIGraph_operators.c | |||||
| ext/cIGraph_selectors.c | |||||
| ext/cIGraph_shortest_paths.c | ext/cIGraph_shortest_paths.c | ||||
| ext/cIGraph_utility.c | ext/cIGraph_utility.c | ||||
| test/tc_add_delete.rb | test/tc_add_delete.rb | ||||
| @@ -15,5 +18,7 @@ test/tc_basic_properties.rb | |||||
| test/tc_basic_query.rb | test/tc_basic_query.rb | ||||
| test/tc_create.rb | test/tc_create.rb | ||||
| test/tc_error_handling.rb | test/tc_error_handling.rb | ||||
| test/tc_iterators.rb | |||||
| test/tc_selectors.rb | |||||
| test/tc_shortest_paths.rb | test/tc_shortest_paths.rb | ||||
| test/test_all.rb | test/test_all.rb | ||||
| @@ -105,6 +105,16 @@ void Init_igraph(){ | |||||
| rb_define_method(cIGraph, "include?", cIGraph_include, 1); | rb_define_method(cIGraph, "include?", cIGraph_include, 1); | ||||
| rb_define_method(cIGraph, "all_vertices", cIGraph_all_v, 0); | |||||
| rb_define_method(cIGraph, "vertices", cIGraph_all_v, 0); | |||||
| rb_define_method(cIGraph, "adjacent_vertices", cIGraph_adj_v, 2); | |||||
| rb_define_method(cIGraph, "nonadjacent_vertices", cIGraph_nonadj_v, 2); | |||||
| rb_define_method(cIGraph, "all_edges", cIGraph_all_e, 1); | |||||
| rb_define_method(cIGraph, "edges", cIGraph_all_e, 1); | |||||
| rb_define_method(cIGraph, "adjacent_edges", cIGraph_adj_e, 2); | |||||
| rb_define_method(cIGraph, "nonadjacent_edges", cIGraph_nonadj_e, 2); | |||||
| rb_define_method(cIGraph, "vcount", cIGraph_vcount, 0); | rb_define_method(cIGraph, "vcount", cIGraph_vcount, 0); | ||||
| rb_define_method(cIGraph, "ecount", cIGraph_ecount, 0); | rb_define_method(cIGraph, "ecount", cIGraph_ecount, 0); | ||||
| @@ -125,8 +135,11 @@ void Init_igraph(){ | |||||
| rb_define_method(cIGraph, "degree", cIGraph_degree,3); | rb_define_method(cIGraph, "degree", cIGraph_degree,3); | ||||
| rb_define_method(cIGraph, "add_edges", cIGraph_add_edges,1); | |||||
| rb_define_method(cIGraph, "add_vertices", cIGraph_add_vertices,1); | |||||
| rb_define_method(cIGraph, "add_edges", cIGraph_add_edges, 1); | |||||
| rb_define_method(cIGraph, "add_vertices", cIGraph_add_vertices, 1); | |||||
| rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, 2); | |||||
| rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); | |||||
| rb_define_method(cIGraph, "are_connected", cIGraph_are_connected,2); | rb_define_method(cIGraph, "are_connected", cIGraph_are_connected,2); | ||||
| rb_define_method(cIGraph, "are_connected?", cIGraph_are_connected,2); | rb_define_method(cIGraph, "are_connected?", cIGraph_are_connected,2); | ||||
| @@ -25,6 +25,15 @@ VALUE cIGraph_each_vertex (VALUE self); | |||||
| VALUE cIGraph_each_edge (VALUE self, VALUE order); | VALUE cIGraph_each_edge (VALUE self, VALUE order); | ||||
| VALUE cIGraph_each_edge_eid(VALUE self, VALUE order); | VALUE cIGraph_each_edge_eid(VALUE self, VALUE order); | ||||
| //Selectors | |||||
| VALUE cIGraph_all_v (VALUE self); | |||||
| VALUE cIGraph_adj_v (VALUE self, VALUE v, VALUE mode); | |||||
| VALUE cIGraph_nonadj_v(VALUE self, VALUE v, VALUE mode); | |||||
| VALUE cIGraph_all_e (VALUE self, VALUE mode); | |||||
| VALUE cIGraph_adj_e (VALUE self, VALUE v, VALUE mode); | |||||
| VALUE cIGraph_nonadj_e(VALUE self, VALUE v, VALUE mode); | |||||
| //Basic query operations | //Basic query operations | ||||
| VALUE cIGraph_vcount (VALUE self); | VALUE cIGraph_vcount (VALUE self); | ||||
| VALUE cIGraph_ecount (VALUE self); | VALUE cIGraph_ecount (VALUE self); | ||||
| @@ -40,6 +49,8 @@ VALUE cIGraph_add_edges (VALUE self, VALUE edges); | |||||
| VALUE cIGraph_add_vertices (VALUE self, VALUE vs); | VALUE cIGraph_add_vertices (VALUE self, VALUE vs); | ||||
| VALUE cIGraph_delete_edges (VALUE self, VALUE edges); | VALUE cIGraph_delete_edges (VALUE self, VALUE edges); | ||||
| VALUE cIGraph_delete_vertices(VALUE self, VALUE vs); | VALUE cIGraph_delete_vertices(VALUE self, VALUE vs); | ||||
| VALUE cIGraph_add_edge (VALUE self, VALUE from, VALUE to); | |||||
| VALUE cIGraph_add_vertex (VALUE self, VALUE v); | |||||
| //Basic properties | //Basic properties | ||||
| VALUE cIGraph_are_connected(VALUE self, VALUE from, VALUE to); | VALUE cIGraph_are_connected(VALUE self, VALUE from, VALUE to); | ||||
| @@ -62,7 +62,9 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ | |||||
| while(vertex != Qnil){ | while(vertex != Qnil){ | ||||
| if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){ | if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){ | ||||
| //If @vertices includes this vertex then raise an error | //If @vertices includes this vertex then raise an error | ||||
| rb_raise(cIGraphError, "Vertex already added to graph"); | |||||
| //Silently ignore | |||||
| //rb_raise(cIGraphError, "Vertex already added to graph"); | |||||
| length--; | |||||
| } else { | } else { | ||||
| //otherwise add a new entry to Hash | //otherwise add a new entry to Hash | ||||
| rb_hash_aset(object_h,vertex,INT2NUM(vertex_n)); | rb_hash_aset(object_h,vertex,INT2NUM(vertex_n)); | ||||
| @@ -76,3 +78,78 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ | |||||
| return INT2NUM(code); | return INT2NUM(code); | ||||
| } | } | ||||
| VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){ | |||||
| igraph_t *graph; | |||||
| igraph_vector_t edge_v; | |||||
| VALUE object_h; | |||||
| int vid; | |||||
| int code = 0; | |||||
| //Initialize edge vector | |||||
| igraph_vector_init_int(&edge_v,0); | |||||
| object_h = rb_iv_get(self,"@object_ids"); | |||||
| Data_Get_Struct(self, igraph_t, graph); | |||||
| if(rb_funcall(object_h,rb_intern("has_key?"),1,from)){ | |||||
| //If @vertices includes this vertex then look up the vertex number | |||||
| vid = NUM2INT(rb_hash_aref(object_h,from)); | |||||
| } else { | |||||
| rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first"); | |||||
| } | |||||
| igraph_vector_push_back(&edge_v,vid); | |||||
| if(rb_funcall(object_h,rb_intern("has_key?"),1,to)){ | |||||
| //If @vertices includes this vertex then look up the vertex number | |||||
| vid = NUM2INT(rb_hash_aref(object_h,to)); | |||||
| } else { | |||||
| rb_raise(cIGraphError, "Unknown vertex in edge array. Use add_vertices first"); | |||||
| } | |||||
| igraph_vector_push_back(&edge_v,vid); | |||||
| code = igraph_add_edges(graph,&edge_v,0); | |||||
| igraph_vector_destroy(&edge_v); | |||||
| return INT2NUM(code); | |||||
| } | |||||
| VALUE cIGraph_add_vertex(VALUE self, VALUE v){ | |||||
| igraph_t *graph; | |||||
| VALUE vertex; | |||||
| VALUE object_h; | |||||
| VALUE id_h; | |||||
| int vertex_n; | |||||
| int code = 0; | |||||
| int length; | |||||
| object_h = rb_iv_get(self,"@object_ids"); | |||||
| id_h = rb_iv_get(self,"@id_objects"); | |||||
| length = 1; | |||||
| vertex_n = NUM2INT(rb_funcall(object_h,rb_intern("length"),0)); | |||||
| Data_Get_Struct(self, igraph_t, graph); | |||||
| //Loop through objects in vertex array | |||||
| if(rb_funcall(object_h,rb_intern("has_key?"),1,v)){ | |||||
| //If @vertices includes this vertex then raise an error | |||||
| //Silently ignore | |||||
| //rb_raise(cIGraphError, "Vertex already added to graph"); | |||||
| length--; | |||||
| } else { | |||||
| //otherwise add a new entry to Hash | |||||
| rb_hash_aset(object_h,v,INT2NUM(vertex_n)); | |||||
| rb_hash_aset(id_h, INT2NUM(vertex_n),v); | |||||
| vertex_n++; | |||||
| } | |||||
| if(length != 0) | |||||
| code = igraph_add_vertices(graph,length,0); | |||||
| return INT2NUM(code); | |||||
| } | |||||
| @@ -12,6 +12,7 @@ VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){ | |||||
| int i; | int i; | ||||
| int j; | int j; | ||||
| VALUE row; | VALUE row; | ||||
| VALUE path_length; | |||||
| VALUE matrix = rb_ary_new(); | VALUE matrix = rb_ary_new(); | ||||
| int n_row; | int n_row; | ||||
| int n_col; | int n_col; | ||||
| @@ -35,7 +36,8 @@ VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){ | |||||
| row = rb_ary_new(); | row = rb_ary_new(); | ||||
| rb_ary_push(matrix,row); | rb_ary_push(matrix,row); | ||||
| for(j=0; j<igraph_matrix_ncol(&res); j++){ | for(j=0; j<igraph_matrix_ncol(&res); j++){ | ||||
| rb_ary_push(row,INT2NUM(MATRIX(res,i,j))); | |||||
| path_length = MATRIX(res,i,j) == n_col ? Qnil : INT2NUM(MATRIX(res,i,j)); | |||||
| rb_ary_push(row,path_length); | |||||
| } | } | ||||
| } | } | ||||
| @@ -14,6 +14,10 @@ class TestGraph < Test::Unit::TestCase | |||||
| graph.add_vertices(['E','F','G','H']) | graph.add_vertices(['E','F','G','H']) | ||||
| assert_equal 8, graph.vcount | assert_equal 8, graph.vcount | ||||
| assert_equal [0], graph.degree(['E'],IGraph::ALL,true) | assert_equal [0], graph.degree(['E'],IGraph::ALL,true) | ||||
| assert_nothing_raised do | |||||
| graph.add_vertices(['H','I']) | |||||
| end | |||||
| assert_equal 9, graph.vcount | |||||
| end | end | ||||
| def test_add_to_empty_graph | def test_add_to_empty_graph | ||||
| @@ -24,4 +28,22 @@ class TestGraph < Test::Unit::TestCase | |||||
| graph.add_edges(['A','B']) | graph.add_edges(['A','B']) | ||||
| assert_equal 1, graph.ecount | assert_equal 1, graph.ecount | ||||
| end | end | ||||
| def test_add_edge | |||||
| graph = IGraph.new(['A','B','C','D'],true) | |||||
| assert_nothing_raised do | |||||
| graph.add_edge('A','D') | |||||
| end | |||||
| assert_equal [2], graph.degree(['A'],IGraph::ALL,true) | |||||
| end | |||||
| def test_add_vertex | |||||
| graph = IGraph.new(['A','B','C','D'],true) | |||||
| assert_nothing_raised do | |||||
| graph.add_vertex('E') | |||||
| end | |||||
| assert_equal 5, graph.vcount | |||||
| assert_equal [0], graph.degree(['E'],IGraph::ALL,true) | |||||
| end | |||||
| end | end | ||||
| @@ -1,5 +1,6 @@ | |||||
| require 'test/unit' | require 'test/unit' | ||||
| require 'igraph' | require 'igraph' | ||||
| require 'mocha' | |||||
| class TestGraph < Test::Unit::TestCase | class TestGraph < Test::Unit::TestCase | ||||
| def test_shortest_paths | def test_shortest_paths | ||||
| @@ -8,11 +9,17 @@ class TestGraph < Test::Unit::TestCase | |||||
| assert_equal 1, m[0][1] | assert_equal 1, m[0][1] | ||||
| assert_equal 0, m[0][0] | assert_equal 0, m[0][0] | ||||
| assert_equal graph.vcount, m[0].size | assert_equal graph.vcount, m[0].size | ||||
| assert_equal graph.vcount, m[0][2] | |||||
| assert_equal nil, m[0][2] | |||||
| end | end | ||||
| def test_get_shortest_paths | |||||
| def test_get_shortest_paths_warn | |||||
| graph = IGraph.new(['A','B','C','D'],true) | graph = IGraph.new(['A','B','C','D'],true) | ||||
| graph.expects(:warn).with("Couldn't reach some vertices") | |||||
| graph.get_shortest_paths('A',['B','C'],IGraph::ALL) | |||||
| end | |||||
| def test_get_shortest_paths | |||||
| graph = IGraph.new(['A','B','C','D'],true) | |||||
| m = graph.get_shortest_paths('A',['B','C'],IGraph::ALL) | m = graph.get_shortest_paths('A',['B','C'],IGraph::ALL) | ||||
| assert_equal ['A','B'], m[0] | assert_equal ['A','B'], m[0] | ||||
| assert_equal [], m[1] | assert_equal [], m[1] | ||||
| @@ -4,6 +4,7 @@ require 'test/unit' | |||||
| require 'tc_create' | require 'tc_create' | ||||
| require 'tc_iterators' | require 'tc_iterators' | ||||
| require 'tc_selectors' | |||||
| require 'tc_add_delete' | require 'tc_add_delete' | ||||
| require 'tc_basic_query' | require 'tc_basic_query' | ||||
| require 'tc_basic_properties' | require 'tc_basic_properties' | ||||