| @@ -41,12 +41,14 @@ end | |||
| hoe.spec.dependencies.delete_if{|dep| dep.name == "hoe"} | |||
| IGRAPH = '/usr/local/include/igraph' | |||
| desc "Uses extconf.rb and make to build the extension" | |||
| task :build_extension => ['ext/igraph.so'] | |||
| SRC = FileList['ext/*.c'] + FileList['ext/*.h'] | |||
| file 'ext/igraph.so' => SRC do | |||
| Dir.chdir('ext') | |||
| system("ruby extconf.rb --with-igraph-dir=$IGRAPH_HOME") | |||
| system("ruby extconf.rb --with-igraph-include=#{IGRAPH}") | |||
| system("make") | |||
| Dir.chdir('..') | |||
| end | |||
| @@ -92,6 +92,17 @@ void Init_igraph(){ | |||
| rb_define_alloc_func(cIGraph, cIGraph_alloc); | |||
| rb_define_method(cIGraph, "initialize", cIGraph_initialize, 2); | |||
| rb_define_method(cIGraph, "each_vertex", cIGraph_each_vertex, 0); | |||
| rb_define_method(cIGraph, "each_edge", cIGraph_each_edge, 1); | |||
| rb_define_method(cIGraph, "each_edge_eid", cIGraph_each_edge_eid,1); | |||
| rb_define_const(cIGraph, "EDGEORDER_ID", INT2NUM(1)); | |||
| rb_define_const(cIGraph, "EDGEORDER_FROM", INT2NUM(2)); | |||
| rb_define_const(cIGraph, "EDGEORDER_TO", INT2NUM(3)); | |||
| rb_define_method(cIGraph, "each", cIGraph_each_vertex, 0); | |||
| rb_include_module(cIGraph, rb_mEnumerable); | |||
| rb_define_method(cIGraph, "include?", cIGraph_include, 1); | |||
| rb_define_method(cIGraph, "vcount", cIGraph_vcount, 0); | |||
| @@ -104,10 +115,10 @@ void Init_igraph(){ | |||
| rb_define_method(cIGraph, "neighbours", cIGraph_neighbors,2); | |||
| rb_define_method(cIGraph, "adjacent", cIGraph_adjacent,2); | |||
| rb_define_const(cIGraph, "IGRAPH_OUT", INT2NUM(1)); | |||
| rb_define_const(cIGraph, "IGRAPH_IN", INT2NUM(2)); | |||
| rb_define_const(cIGraph, "IGRAPH_ALL", INT2NUM(3)); | |||
| rb_define_const(cIGraph, "IGRAPH_TOTAL", INT2NUM(4)); | |||
| rb_define_const(cIGraph, "OUT", INT2NUM(1)); | |||
| rb_define_const(cIGraph, "IN", INT2NUM(2)); | |||
| rb_define_const(cIGraph, "ALL", INT2NUM(3)); | |||
| rb_define_const(cIGraph, "TOTAL", INT2NUM(4)); | |||
| rb_define_method(cIGraph, "is_directed", cIGraph_is_directed,0); | |||
| rb_define_method(cIGraph, "is_directed?", cIGraph_is_directed,0); | |||
| @@ -20,6 +20,11 @@ void cIGraph_free(void *p); | |||
| VALUE cIGraph_alloc(VALUE klass); | |||
| VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed); | |||
| //Iterators | |||
| VALUE cIGraph_each_vertex (VALUE self); | |||
| VALUE cIGraph_each_edge (VALUE self, VALUE order); | |||
| VALUE cIGraph_each_edge_eid(VALUE self, VALUE order); | |||
| //Basic query operations | |||
| VALUE cIGraph_vcount (VALUE self); | |||
| VALUE cIGraph_ecount (VALUE self); | |||
| @@ -0,0 +1,80 @@ | |||
| #include "igraph.h" | |||
| #include "ruby.h" | |||
| #include "cIGraph.h" | |||
| VALUE cIGraph_each_vertex(VALUE self){ | |||
| igraph_t *graph; | |||
| igraph_vs_t vs; | |||
| igraph_vit_t vit; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_vs_all(&vs); | |||
| igraph_vit_create(graph, vs, &vit); | |||
| while(!IGRAPH_VIT_END(vit)) { | |||
| rb_yield(cIGraph_get_vertex_object(self,IGRAPH_VIT_GET(vit))); | |||
| IGRAPH_VIT_NEXT(vit); | |||
| } | |||
| igraph_vit_destroy(&vit); | |||
| igraph_vs_destroy(&vs); | |||
| return Qnil; | |||
| } | |||
| VALUE cIGraph_each_edge(VALUE self, VALUE order){ | |||
| igraph_t *graph; | |||
| igraph_es_t es; | |||
| igraph_eit_t eit; | |||
| igraph_edgeorder_type_t order_t = NUM2INT(order); | |||
| igraph_integer_t from; | |||
| igraph_integer_t to; | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_es_all(&es,order_t); | |||
| igraph_eit_create(graph, es, &eit); | |||
| while(!IGRAPH_EIT_END(eit)) { | |||
| igraph_edge(graph,IGRAPH_EIT_GET(eit),&from,&to); | |||
| rb_yield(rb_ary_new3(2, | |||
| cIGraph_get_vertex_object(self, from), | |||
| cIGraph_get_vertex_object(self, to))); | |||
| IGRAPH_EIT_NEXT(eit); | |||
| } | |||
| igraph_eit_destroy(&eit); | |||
| igraph_es_destroy(&es); | |||
| return Qnil; | |||
| } | |||
| VALUE cIGraph_each_edge_eid(VALUE self, VALUE order){ | |||
| igraph_t *graph; | |||
| igraph_es_t es; | |||
| igraph_eit_t eit; | |||
| igraph_edgeorder_type_t order_t = NUM2INT(order); | |||
| Data_Get_Struct(self, igraph_t, graph); | |||
| igraph_es_all(&es,order_t); | |||
| igraph_eit_create(graph, es, &eit); | |||
| while(!IGRAPH_EIT_END(eit)) { | |||
| rb_yield(INT2NUM(IGRAPH_EIT_GET(eit))); | |||
| IGRAPH_EIT_NEXT(eit); | |||
| } | |||
| igraph_eit_destroy(&eit); | |||
| igraph_es_destroy(&es); | |||
| return Qnil; | |||
| } | |||
| @@ -31,7 +31,13 @@ VALUE cIGraph_get_vertex_object(VALUE graph, igraph_integer_t n){ | |||
| int cIGraph_vertex_arr_to_id_vec(VALUE graph, VALUE va, igraph_vector_t *nv){ | |||
| VALUE vertex; | |||
| VALUE tmp; | |||
| tmp = rb_check_array_type(va); | |||
| if(NIL_P(tmp)) | |||
| rb_raise(cIGraphError, "Array expected\n"); | |||
| //Initialize edge vector | |||
| igraph_vector_init_int(nv,0); | |||
| vertex = rb_ary_shift(va); | |||
| @@ -5,7 +5,7 @@ class TestGraph < Test::Unit::TestCase | |||
| def test_add_edges | |||
| graph = IGraph.new(['A','B','C','D'],true) | |||
| graph.add_edges(['A','C']) | |||
| assert_equal [2], graph.degree(['A'],IGraph::IGRAPH_ALL,true) | |||
| assert_equal [2], graph.degree(['A'],IGraph::ALL,true) | |||
| end | |||
| def test_add_vertices | |||
| @@ -13,7 +13,7 @@ class TestGraph < Test::Unit::TestCase | |||
| assert_equal 4, graph.vcount | |||
| graph.add_vertices(['E','F','G','H']) | |||
| assert_equal 8, graph.vcount | |||
| assert_equal [0], graph.degree(['E'],IGraph::IGRAPH_ALL,true) | |||
| assert_equal [0], graph.degree(['E'],IGraph::ALL,true) | |||
| end | |||
| def test_add_to_empty_graph | |||
| @@ -21,20 +21,20 @@ class TestGraph < Test::Unit::TestCase | |||
| def test_neighbours | |||
| assert_nothing_raised do | |||
| IGraph.new(['A','B','C','D'],true).neighbors('A',IGraph::IGRAPH_ALL) | |||
| IGraph.new(['A','B','C','D'],true).neighbors('A',IGraph::ALL) | |||
| end | |||
| graph = IGraph.new(['A','B','C','D'],true) | |||
| assert_equal ['B'], graph.neighbors('A',IGraph::IGRAPH_ALL) | |||
| assert_equal ['D'], graph.neighbors('C',IGraph::IGRAPH_ALL) | |||
| assert_equal ['B'], graph.neighbors('A',IGraph::ALL) | |||
| assert_equal ['D'], graph.neighbors('C',IGraph::ALL) | |||
| end | |||
| def test_adjacent | |||
| assert_nothing_raised do | |||
| IGraph.new(['A','B','C','D'],true).adjacent('A',IGraph::IGRAPH_ALL) | |||
| IGraph.new(['A','B','C','D'],true).adjacent('A',IGraph::ALL) | |||
| end | |||
| graph = IGraph.new(['A','B','C','D'],true) | |||
| eid1 = graph.get_eid('A','B') | |||
| eid2 = graph.adjacent('A',IGraph::IGRAPH_ALL)[0] | |||
| eid2 = graph.adjacent('A',IGraph::ALL)[0] | |||
| assert_equal eid1, eid2 | |||
| end | |||
| @@ -45,7 +45,10 @@ class TestGraph < Test::Unit::TestCase | |||
| def test_degree | |||
| graph = IGraph.new(['A','B','C','D'],true) | |||
| assert_equal [1], graph.degree(['A'], IGraph::IGRAPH_ALL,true) | |||
| assert_equal [1,1],graph.degree(['A','B'],IGraph::IGRAPH_ALL,true) | |||
| assert_equal [1], graph.degree(['A'], IGraph::ALL,true) | |||
| assert_equal [1,1],graph.degree(['A','B'],IGraph::ALL,true) | |||
| assert_raises IGraphError do | |||
| graph.degree('A',IGraph::ALL,true) | |||
| end | |||
| end | |||
| end | |||
| @@ -4,7 +4,7 @@ require 'igraph' | |||
| class TestGraph < Test::Unit::TestCase | |||
| def test_shortest_paths | |||
| graph = IGraph.new(['A','B','C','D'],true) | |||
| m = graph.shortest_paths(['A'],IGraph::IGRAPH_ALL) | |||
| m = graph.shortest_paths(['A'],IGraph::ALL) | |||
| assert_equal 1, m[0][1] | |||
| assert_equal 0, m[0][0] | |||
| assert_equal graph.vcount, m[0].size | |||
| @@ -13,7 +13,7 @@ class TestGraph < Test::Unit::TestCase | |||
| def test_get_shortest_paths | |||
| graph = IGraph.new(['A','B','C','D'],true) | |||
| m = graph.get_shortest_paths('A',['B','C'],IGraph::IGRAPH_ALL) | |||
| m = graph.get_shortest_paths('A',['B','C'],IGraph::ALL) | |||
| assert_equal ['A','B'], m[0] | |||
| assert_equal [], m[1] | |||
| end | |||
| @@ -3,6 +3,7 @@ | |||
| require 'test/unit' | |||
| require 'tc_create' | |||
| require 'tc_iterators' | |||
| require 'tc_add_delete' | |||
| require 'tc_basic_query' | |||
| require 'tc_basic_properties' | |||