| @@ -8,6 +8,9 @@ ext/cIGraph_add_delete.c | |||
| ext/cIGraph_basic_properties.c | |||
| ext/cIGraph_basic_query.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_utility.c | |||
| test/tc_add_delete.rb | |||
| @@ -15,5 +18,7 @@ test/tc_basic_properties.rb | |||
| test/tc_basic_query.rb | |||
| test/tc_create.rb | |||
| test/tc_error_handling.rb | |||
| test/tc_iterators.rb | |||
| test/tc_selectors.rb | |||
| test/tc_shortest_paths.rb | |||
| test/test_all.rb | |||
| @@ -105,6 +105,16 @@ void Init_igraph(){ | |||
| 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, "ecount", cIGraph_ecount, 0); | |||
| @@ -125,8 +135,11 @@ void Init_igraph(){ | |||
| 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); | |||
| @@ -25,6 +25,15 @@ VALUE cIGraph_each_vertex (VALUE self); | |||
| VALUE cIGraph_each_edge (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 | |||
| VALUE cIGraph_vcount (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_delete_edges (VALUE self, VALUE edges); | |||
| 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 | |||
| 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){ | |||
| if(rb_funcall(object_h,rb_intern("has_key?"),1,vertex)){ | |||
| //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 { | |||
| //otherwise add a new entry to Hash | |||
| rb_hash_aset(object_h,vertex,INT2NUM(vertex_n)); | |||
| @@ -76,3 +78,78 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ | |||
| 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 j; | |||
| VALUE row; | |||
| VALUE path_length; | |||
| VALUE matrix = rb_ary_new(); | |||
| int n_row; | |||
| int n_col; | |||
| @@ -35,7 +36,8 @@ VALUE cIGraph_shortest_paths(VALUE self, VALUE from, VALUE mode){ | |||
| row = rb_ary_new(); | |||
| rb_ary_push(matrix,row); | |||
| 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']) | |||
| assert_equal 8, graph.vcount | |||
| 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 | |||
| def test_add_to_empty_graph | |||
| @@ -24,4 +28,22 @@ class TestGraph < Test::Unit::TestCase | |||
| graph.add_edges(['A','B']) | |||
| assert_equal 1, graph.ecount | |||
| 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 | |||
| @@ -1,5 +1,6 @@ | |||
| require 'test/unit' | |||
| require 'igraph' | |||
| require 'mocha' | |||
| class TestGraph < Test::Unit::TestCase | |||
| def test_shortest_paths | |||
| @@ -8,11 +9,17 @@ class TestGraph < Test::Unit::TestCase | |||
| assert_equal 1, m[0][1] | |||
| assert_equal 0, m[0][0] | |||
| assert_equal graph.vcount, m[0].size | |||
| assert_equal graph.vcount, m[0][2] | |||
| assert_equal nil, m[0][2] | |||
| end | |||
| def test_get_shortest_paths | |||
| def test_get_shortest_paths_warn | |||
| 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) | |||
| assert_equal ['A','B'], m[0] | |||
| assert_equal [], m[1] | |||
| @@ -4,6 +4,7 @@ require 'test/unit' | |||
| require 'tc_create' | |||
| require 'tc_iterators' | |||
| require 'tc_selectors' | |||
| require 'tc_add_delete' | |||
| require 'tc_basic_query' | |||
| require 'tc_basic_properties' | |||