From 06b4e6deae72235a15456f970eed366e3cb28b68 Mon Sep 17 00:00:00 2001 From: alexgutteridge Date: Tue, 3 Jul 2007 07:58:02 +0000 Subject: [PATCH] --- Rakefile.rb | 2 +- ext/cIGraph.c | 56 ++++++++++------- ext/cIGraph_add_delete.c | 64 ++++++++++++++++++++ ext/cIGraph_basic_properties.c | 13 ++++ ext/cIGraph_basic_query.c | 107 +++++++++++++++++++++++++++++++++ ext/cIGraph_iterators.c | 57 +++++++++++++++++- 6 files changed, 274 insertions(+), 25 deletions(-) diff --git a/Rakefile.rb b/Rakefile.rb index 50d7798..93b24cd 100644 --- a/Rakefile.rb +++ b/Rakefile.rb @@ -7,7 +7,7 @@ hoe = Hoe.new("igraph",'0.1') do |p| p.author = "Alex Gutteridge" p.email = "alexg@kuicr.kyoto-u.ac.jp" - p.url = "http://web.kuicr.kyoto-u.ac.jp/~alexg/igraph/" + p.url = "http://igraph.rubyforge.org/" p.description = p.paragraphs_of("README.txt",1..3)[0] p.summary = p.paragraphs_of("README.txt",1)[0] diff --git a/ext/cIGraph.c b/ext/cIGraph.c index 7a48563..cd3599a 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -19,14 +19,23 @@ VALUE cIGraph_alloc(VALUE klass){ } /* call-seq: - * IGraph.new(edges,directed) -> graph + * IGraph.new(edges,directed) -> IGraph * - * Creates a new IGraph graph with the edges specified in the edge Array. + * Creates a new IGraph graph with the edges specified in the edges Array. * The first two elements define the first edge (the order is from,to for * directed graphs). The next two define the second edge and so on. The - * Array should contain an even number of elements. + * Array should contain an even number of elements. Graph elements can be + * any ruby object. + * * The boolean value directed specifies whether a directed or undirected * graph is created. + * + * Example: + * + * IGraph.new([1,2,3,4],true) + * + * Creates a graph with four vertices. Vertex 1 is connected to vertex 2. + * Vertex 3 is connected to vertex 4. */ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){ @@ -82,7 +91,8 @@ VALUE cIGraph_initialize(VALUE self, VALUE edges, VALUE directed){ } /* Interface to the iGraph[http://cneurocvs.rmki.kfki.hu/igraph/] library - * for graph computation + * for graph and network computation. See IGraph#new for how to create a + * graph and get started. */ void Init_igraph(){ @@ -92,9 +102,9 @@ 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_method(cIGraph, "each_vertex", cIGraph_each_vertex, 0); /* in cIGraph_iterators.c */ + rb_define_method(cIGraph, "each_edge", cIGraph_each_edge, 1); /* in cIGraph_iterators.c */ + rb_define_method(cIGraph, "each_edge_eid", cIGraph_each_edge_eid,1); /* in cIGraph_iterators.c */ rb_define_const(cIGraph, "EDGEORDER_ID", INT2NUM(1)); rb_define_const(cIGraph, "EDGEORDER_FROM", INT2NUM(2)); @@ -106,24 +116,24 @@ 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, "vertices", cIGraph_all_v, 0); /* in cIGraph_selectors.c */ + rb_define_method(cIGraph, "adjacent_vertices", cIGraph_adj_v, 2); /* in cIGraph_selectors.c */ + rb_define_method(cIGraph, "nonadjacent_vertices", cIGraph_nonadj_v, 2); /* in cIGraph_selectors.c */ 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); + rb_define_method(cIGraph, "vcount", cIGraph_vcount, 0); /* in cIGraph_basic_query.c */ + rb_define_method(cIGraph, "ecount", cIGraph_ecount, 0); /* in cIGraph_basic_query.c */ - rb_define_method(cIGraph, "edge", cIGraph_edge, 1); - rb_define_method(cIGraph, "get_eid", cIGraph_get_eid, 2); + rb_define_method(cIGraph, "edge", cIGraph_edge, 1); /* in cIGraph_basic_query.c */ + rb_define_method(cIGraph, "get_eid", cIGraph_get_eid, 2); /* in cIGraph_basic_query.c */ rb_define_method(cIGraph, "neighbors", cIGraph_neighbors,2); - rb_define_method(cIGraph, "neighbours", cIGraph_neighbors,2); - rb_define_method(cIGraph, "adjacent", cIGraph_adjacent,2); + rb_define_method(cIGraph, "neighbours", cIGraph_neighbors,2); /* in cIGraph_basic_query.c */ + rb_define_method(cIGraph, "adjacent", cIGraph_adjacent,2); /* in cIGraph_basic_query.c */ rb_define_const(cIGraph, "OUT", INT2NUM(1)); rb_define_const(cIGraph, "IN", INT2NUM(2)); @@ -131,18 +141,18 @@ void Init_igraph(){ 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); + rb_define_method(cIGraph, "is_directed?", cIGraph_is_directed,0); /* in cIGraph_basic_query.c */ - rb_define_method(cIGraph, "degree", cIGraph_degree,3); + rb_define_method(cIGraph, "degree", cIGraph_degree,3); /* in cIGraph_basic_query.c */ - 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); /* in cIGraph_add_delete.c */ + rb_define_method(cIGraph, "add_vertices", cIGraph_add_vertices, 1); /* in cIGraph_add_delete.c */ - rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, 2); - rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); + rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, 2); /* in cIGraph_add_delete.c */ + rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); /* in cIGraph_add_delete.c */ 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); /* in cIGraph_basic_properties.c */ rb_define_method(cIGraph, "shortest_paths", cIGraph_shortest_paths,2); rb_define_method(cIGraph, "get_shortest_paths", cIGraph_get_shortest_paths,3); diff --git a/ext/cIGraph_add_delete.c b/ext/cIGraph_add_delete.c index 3367f2e..fe09b51 100644 --- a/ext/cIGraph_add_delete.c +++ b/ext/cIGraph_add_delete.c @@ -2,6 +2,23 @@ #include "ruby.h" #include "cIGraph.h" +/* call-seq: + * graph.add_edges(edges) -> Fixnum + * + * Adds the edges in the edges Array to the graph. Edges are specified as an + * Array in the same way as with IGraph#new. + * + * Returns 0 on success. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.add_edges([1,4,2,3]) + * + * Adds an extra directed edge to this trivial graph. Note that vertices + * must have already been added to the graph before they can be used in + * an edge (throws a IGraphError otherwise). + */ VALUE cIGraph_add_edges(VALUE self, VALUE edges){ igraph_t *graph; @@ -40,6 +57,21 @@ VALUE cIGraph_add_edges(VALUE self, VALUE edges){ } +/* call-seq: + * graph.add_vertices(vs) -> Fixnum + * + * Adds the vertices in the vs Array to the graph. + * + * Returns 0 on success. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.add_vertices([5,6,7,8]) + * + * Adds 4 extra vertices to this graph. IGraph will silently ignore attempts + * to add a vertex twice to the same graph. + */ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ igraph_t *graph; @@ -79,6 +111,22 @@ VALUE cIGraph_add_vertices(VALUE self, VALUE vs){ } +/* call-seq: + * graph.add_edge(from,to) -> Fixnum + * + * Adds an edge between the two vertices given. This is just a convinience + * method, it is possible to use IGraph#add_edges to add a single edge as well + * + * Returns 0 on success. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.add_edge(1,4) + * + * Note that vertices must have already been added to the graph before + * they can be used in an edge (throws a IGraphError otherwise). + */ VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){ igraph_t *graph; @@ -117,6 +165,22 @@ VALUE cIGraph_add_edge(VALUE self, VALUE from, VALUE to){ } +/* call-seq: + * graph.add_vertex(v) -> Fixnum + * + * Adds the vertex to the graph. This is just a convinience method it is + * also possible to use IGraph#add_vertices to add a single vertex. + * + * Returns 0 on success. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.add_vertex(5) + * + * Adds 1 extra vertex to this graph. IGraph will silently ignore attempts + * to add a vertex twice to the same graph. + */ VALUE cIGraph_add_vertex(VALUE self, VALUE v){ igraph_t *graph; diff --git a/ext/cIGraph_basic_properties.c b/ext/cIGraph_basic_properties.c index 15bc8dd..9208c83 100644 --- a/ext/cIGraph_basic_properties.c +++ b/ext/cIGraph_basic_properties.c @@ -2,6 +2,19 @@ #include "ruby.h" #include "cIGraph.h" +/* call-seq: + * graph.are_connected?(from,to) -> true/false + * + * Returns a boolean specifying whether the two vertices specified are + * connected by an edge. + * + * Example: + * + * IGraph.new([1,2,3,4],true) + * graph.are_connected?(1,2) #returns true + * + */ + VALUE cIGraph_are_connected(VALUE self, VALUE from, VALUE to){ igraph_t *graph; diff --git a/ext/cIGraph_basic_query.c b/ext/cIGraph_basic_query.c index ea23716..fe38038 100644 --- a/ext/cIGraph_basic_query.c +++ b/ext/cIGraph_basic_query.c @@ -2,6 +2,18 @@ #include "ruby.h" #include "cIGraph.h" +/* call-seq: + * graph.vcount() -> Fixnum + * + * Returns the number of vertices in the IGraph object. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.vcount # returns 4 + * + */ + VALUE cIGraph_vcount(VALUE self){ igraph_t *graph; @@ -9,6 +21,18 @@ VALUE cIGraph_vcount(VALUE self){ return INT2NUM(igraph_vcount(graph)); } +/* call-seq: + * graph.ecount() -> Fixnum + * + * Returns the number of edges in the IGraph object. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.ecount # returns 2 + * + */ + VALUE cIGraph_ecount(VALUE self){ igraph_t *graph; @@ -16,6 +40,19 @@ VALUE cIGraph_ecount(VALUE self){ return INT2NUM(igraph_ecount(graph)); } +/* call-seq: + * graph.edge(eid) -> [from,to] + * + * Returns an Array comprising the vertices making up the edge represented + * by the edge id eid. You can find the id of an edge using IGraph#get_eid. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.edge(1) # returns [1,2] + * + */ + VALUE cIGraph_edge(VALUE self, VALUE eid){ igraph_t *graph; igraph_integer_t from = 0; @@ -34,6 +71,19 @@ VALUE cIGraph_edge(VALUE self, VALUE eid){ } +/* call-seq: + * graph.get_eid(from,to,directed) -> Fixnum + * + * Returns the edge id of the edge connecting the vertices from and to. + * directed is a boolean specifying whether to search for directed edges + * in a directed graph. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.get_eid(1,2,true) # returns 1 + * + */ VALUE cIGraph_get_eid(VALUE self, VALUE from, VALUE to, VALUE directed){ igraph_t *graph; igraph_integer_t eid = 0; @@ -55,6 +105,22 @@ VALUE cIGraph_get_eid(VALUE self, VALUE from, VALUE to, VALUE directed){ } +/* call-seq: + * graph.neighbours(vertex,mode) -> Array + * + * Returns an Array of the neighbouring vertices to vertex. mode defines + * the way adjacent vertices are searched for directed graphs. It can have + * the following values: IGraph::OUT, vertices reachable by an edge from the + * specified vertex are searched, IGraph::IN, vertices from which the + * specified vertex is reachable are searched. IGraph::ALL, both kind of + * vertices are searched. This parameter is ignored for undirected graphs. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.neighbours(1,IGraph::ALL) # returns [2] + * + */ VALUE cIGraph_neighbors(VALUE self, VALUE v, VALUE mode){ igraph_t *graph; @@ -82,6 +148,21 @@ VALUE cIGraph_neighbors(VALUE self, VALUE v, VALUE mode){ } +/* call-seq: + * graph.adjacent(vertex,mode) -> Array + * + * Returns an Array of the adjacent edge ids to vertex. mode defines + * the way adjacent edges are searched for directed graphs. It can have + * the following values: IGraph::OUT means only outgoing edges, IGraph::IN + * only incoming edges, IGraph::ALL both. This parameter is ignored for + * undirected graphs. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.adjacent(1,IGraph::ALL) # returns [1] + * + */ VALUE cIGraph_adjacent(VALUE self, VALUE v, VALUE mode){ igraph_t *graph; @@ -109,6 +190,17 @@ VALUE cIGraph_adjacent(VALUE self, VALUE v, VALUE mode){ } +/* call-seq: + * graph.is_directed?() -> true/false + * + * Returns a boolean specifying whether the graph is directed or not. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.is_directed? #returns true + * + */ VALUE cIGraph_is_directed(VALUE self){ igraph_t *graph; @@ -118,6 +210,21 @@ VALUE cIGraph_is_directed(VALUE self){ } +/* call-seq: + * graph.degree(vs,mode,loops) -> Array + * + * Returns an Array of Integers specifying the degree of each of the + * vertices specified in the vs Array. mode defines the type of the degree. + * IGraph::OUT, out-degree, IGraph::IN, in-degree, IGraph::ALL, total degree + * (sum of the in- and out-degree). This parameter is ignored for undirected + * graphs. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.is_directed? #returns true + * + */ VALUE cIGraph_degree(VALUE self, VALUE v, VALUE mode, VALUE loops){ igraph_t *graph; igraph_vs_t vids; diff --git a/ext/cIGraph_iterators.c b/ext/cIGraph_iterators.c index 6478288..6ce74ea 100644 --- a/ext/cIGraph_iterators.c +++ b/ext/cIGraph_iterators.c @@ -2,6 +2,22 @@ #include "ruby.h" #include "cIGraph.h" +/* call-seq: + * graph.each_vertex{|v| } -> nil + * + * Iterates through all the vertices in the graph. Also accessible via + * IGraph#each which is used by Enumerable to provide other methods. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.each do |v| + * puts v + * end + * g.find_all{|v| v > 2} #returns [3,4] + * + */ + VALUE cIGraph_each_vertex(VALUE self){ igraph_t *graph; @@ -24,7 +40,26 @@ VALUE cIGraph_each_vertex(VALUE self){ return Qnil; } - +/* call-seq: + * graph.each_edge(mode){|v,w| } -> nil + * + * Iterates through all the edges in the graph. mode specifies the order the + * edges are returned: IGRAPH_EDGEORDER_ID, edge id order. + * IGRAPH_EDGEORDER_FROM, vertex id order, the id of the source vertex + * counts for directed graphs. The order of the adjacent edges of a given + * vertex is arbitrary. IGRAPH_EDGEORDER_TO, vertex id order, the id of the + * target vertex counts for directed graphs. The order of the adjacent edges + * of a given vertex is arbitrary. For undirected graph the latter two are + * the same. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.each_edge(IGraph::EDGORDER_ID) do |v,w| + * puts "#{v} -> #{w}" + * end + * + */ VALUE cIGraph_each_edge(VALUE self, VALUE order){ igraph_t *graph; @@ -55,6 +90,26 @@ VALUE cIGraph_each_edge(VALUE self, VALUE order){ } +/* call-seq: + * graph.each_edge_eid(mode){|id| } -> nil + * + * Iterates through all the edges in the graph. mode specifies the order the + * edges are returned: IGRAPH_EDGEORDER_ID, edge id order. + * IGRAPH_EDGEORDER_FROM, vertex id order, the id of the source vertex + * counts for directed graphs. The order of the adjacent edges of a given + * vertex is arbitrary. IGRAPH_EDGEORDER_TO, vertex id order, the id of the + * target vertex counts for directed graphs. The order of the adjacent edges + * of a given vertex is arbitrary. For undirected graph the latter two are + * the same. + * + * Example: + * + * g = IGraph.new([1,2,3,4],true) + * g.each_edge(IGraph::EDGORDER_ID) do |id| + * puts id + * end + * + */ VALUE cIGraph_each_edge_eid(VALUE self, VALUE order){ igraph_t *graph;