From e50abb37ab470073e2f5eea05ac4c8e3c4cf9418 Mon Sep 17 00:00:00 2001 From: alexgutteridge Date: Mon, 2 Jul 2007 07:48:05 +0000 Subject: [PATCH] git-svn-id: http://igraph.rubyforge.org/svn/trunk@4 71f48855-0bbf-4aa5-930d-4df415e86613 --- Rakefile.rb | 4 +- ext/cIGraph.c | 19 ++++++++-- ext/cIGraph.h | 5 +++ ext/cIGraph_iterators.c | 80 +++++++++++++++++++++++++++++++++++++++ ext/cIGraph_utility.c | 6 +++ test/tc_add_delete.rb | 4 +- test/tc_basic_query.rb | 17 +++++---- test/tc_shortest_paths.rb | 4 +- test/test_all.rb | 1 + 9 files changed, 124 insertions(+), 16 deletions(-) create mode 100644 ext/cIGraph_iterators.c diff --git a/Rakefile.rb b/Rakefile.rb index c489305..50d7798 100644 --- a/Rakefile.rb +++ b/Rakefile.rb @@ -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 diff --git a/ext/cIGraph.c b/ext/cIGraph.c index 466abcd..182db73 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -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); diff --git a/ext/cIGraph.h b/ext/cIGraph.h index 1fb7012..38b56b0 100644 --- a/ext/cIGraph.h +++ b/ext/cIGraph.h @@ -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); diff --git a/ext/cIGraph_iterators.c b/ext/cIGraph_iterators.c new file mode 100644 index 0000000..6478288 --- /dev/null +++ b/ext/cIGraph_iterators.c @@ -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; + +} diff --git a/ext/cIGraph_utility.c b/ext/cIGraph_utility.c index 3326196..d6a04c7 100644 --- a/ext/cIGraph_utility.c +++ b/ext/cIGraph_utility.c @@ -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); diff --git a/test/tc_add_delete.rb b/test/tc_add_delete.rb index 478d55e..16dd8f2 100644 --- a/test/tc_add_delete.rb +++ b/test/tc_add_delete.rb @@ -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 diff --git a/test/tc_basic_query.rb b/test/tc_basic_query.rb index d987c34..c6c3ca2 100644 --- a/test/tc_basic_query.rb +++ b/test/tc_basic_query.rb @@ -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 diff --git a/test/tc_shortest_paths.rb b/test/tc_shortest_paths.rb index e9a95a2..9a34b48 100644 --- a/test/tc_shortest_paths.rb +++ b/test/tc_shortest_paths.rb @@ -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 diff --git a/test/test_all.rb b/test/test_all.rb index f5cecfa..066d79d 100644 --- a/test/test_all.rb +++ b/test/test_all.rb @@ -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'