git-svn-id: http://igraph.rubyforge.org/svn/trunk@23 71f48855-0bbf-4aa5-930d-4df415e86613

This commit is contained in:
alexgutteridge 2007-08-07 04:50:38 +00:00
parent 61826fa8cd
commit f8e5537bef
15 changed files with 195 additions and 69 deletions

View File

@ -1,3 +1,10 @@
= 0.1 2007-06-29
= 0.2 2007-07-31
* First version
* First public (announced) release
* Updated functions and documentation
= 0.1 2007-07-16
* First private release
* Graph generation and manipulation functions implemented
* Selection of basic querying functions implemented

View File

@ -9,10 +9,12 @@ ext/cIGraph_attribute_handler.c
ext/cIGraph_basic_properties.c
ext/cIGraph_basic_query.c
ext/cIGraph_error_handlers.c
ext/cIGraph_file.c
ext/cIGraph_iterators.c
ext/cIGraph_operators.c
ext/cIGraph_selectors.c
ext/cIGraph_shortest_paths.c
ext/cIGraph_topological_sort.c
ext/cIGraph_utility.c
ext/cIGraph_vertex_neighbourhood.c
test/tc_add_delete.rb
@ -21,8 +23,10 @@ test/tc_basic_properties.rb
test/tc_basic_query.rb
test/tc_create.rb
test/tc_error_handling.rb
test/tc_file_read_write.rb
test/tc_iterators.rb
test/tc_selectors.rb
test/tc_shortest_paths.rb
test/tc_topological_sort.rb
test/tc_vertex_neighbourhood.rb
test/test_all.rb

View File

@ -1,27 +1,36 @@
== Introduction
IGraph is a Ruby extension for using the igraph library ([http://cneurocvs.rmki.kfki.hu/igraph/]). igraph is a library for creating and manipulating graphs with a particular emphasis on network analysis functions.
IGraph is a Ruby extension for interfacing with the C igraph library (http://cneurocvs.rmki.kfki.hu/igraph/). igraph is a library for creating and manipulating graphs with a particular emphasis on network analysis functions.
IGraph is currently pre-alpha status and should be considered unstable. There are functions for building and querying simple graphs as well as shortest path calculations.
IGraph is currently pre-alpha status and although the basic graph creation and manipulation functions are implemented the API should be considered subject to change. Basic query functions and a few others such as shortest path and sorting functions are also implemented.
All bug reports, feature request and patches are welcome.
All bug reports, feature requests and patches are welcome. Please email alexg (at) kuicr.kyoto-u.ac.jp or use the rubyforge forums: http://rubyforge.org/forum/?group_id=3943
== Installation
A working igraph library installation is required.
A working igraph library installation is required. Please see the igraph homepage (http://cneurocvs.rmki.kfki.hu/igraph/) for details on installing igraph.
An IGraph gem is available. The installation requires the location of your igraph headers and library to compile the extension. E.g. under Ubuntu linux:
IGraph is available as a gem. The installation requires the location of your igraph headers and library to compile the extension. For example, under Ubuntu linux the following command succesfully compiles and installs (you may need to be root):
gem install igraph -- --with-igraph-include=/usr/local/include/igraph
== Documentation
Graph objects are represented in the IGraph class. See the IGraph class documentation for a list of available methods available to build and query graph objects. Any object can be used as a vertex and any edge can be annotated with any kind of object.
Note that many functions require 'mode' constants to tell igraph how you want certain calculations to be made. The constants are listed under the IGraph documentation and should also be made explicit in each methods documentation.
Here is a very quick and simple example:
require 'igraph'
#Create an empty directed graph
graph = IGraph.new([],true)
#Add two edges (unannotated)
graph.add_edges([1,2,3,4])
#Count the number of vertices
graph.vcount # returns 4
== License

View File

@ -113,6 +113,27 @@ VALUE cIGraph_initialize(int argc, VALUE *argv, VALUE self){
}
VALUE cIGraph_init_copy(VALUE copy, VALUE orig){
igraph_t *orig_graph;
igraph_t *copy_graph;
if (copy == orig)
return copy;
if(TYPE(orig) != T_DATA || RDATA(orig)->dfree != (RUBY_DATA_FUNC)cIGraph_free){
rb_raise(rb_eTypeError, "Wrong argument type.");
}
Data_Get_Struct(copy, igraph_t, copy_graph);
Data_Get_Struct(orig, igraph_t, orig_graph);
igraph_copy(copy_graph,orig_graph);
return copy;
}
/* Interface to the iGraph[http://cneurocvs.rmki.kfki.hu/igraph/] library
* for graph and network computation. See IGraph#new for how to create a
* graph and get started.
@ -125,10 +146,12 @@ void Init_igraph(){
rb_define_alloc_func(cIGraph, cIGraph_alloc);
rb_define_method(cIGraph, "initialize", cIGraph_initialize, -1);
rb_define_method(cIGraph, "initialize_copy", cIGraph_init_copy, 1);
rb_define_method(cIGraph, "[]", cIGraph_get_edge_attr, 2);
rb_define_method(cIGraph, "[]=", cIGraph_set_edge_attr, 3);
rb_define_method(cIGraph, "get_edge_attr", cIGraph_get_edge_attr, 2);
rb_define_method(cIGraph, "[]", cIGraph_get_edge_attr, 2); /* in cIGraph_attribute_handler.c */
rb_define_method(cIGraph, "[]=", cIGraph_set_edge_attr, 3); /* in cIGraph_attribute_handler.c */
rb_define_alias(cIGraph, "get_edge_attr", "[]");
//rb_define_method(cIGraph, "get_edge_attr", cIGraph_get_edge_attr, 2);
rb_define_method(cIGraph, "set_edge_attr", cIGraph_set_edge_attr, 3);
rb_define_method(cIGraph, "each_vertex", cIGraph_each_vertex, 0); /* in cIGraph_iterators.c */
@ -175,12 +198,13 @@ void Init_igraph(){
rb_define_method(cIGraph, "degree", cIGraph_degree,3); /* in cIGraph_basic_query.c */
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_vertices", cIGraph_add_vertices, 1); /* in cIGraph_add_delete.c */
rb_define_method(cIGraph, "add_edge", cIGraph_add_edge, -1); /* in cIGraph_add_delete.c */
rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); /* in cIGraph_add_delete.c */
rb_define_method(cIGraph, "add_vertex", cIGraph_add_vertex, 1); /* in cIGraph_add_delete.c */
rb_define_method(cIGraph, "delete_edge", cIGraph_delete_edge, 2); /* in cIGraph_add_delete.c */
rb_define_method(cIGraph, "delete_edge", cIGraph_delete_edge, 2); /* in cIGraph_add_delete.c */
rb_define_method(cIGraph, "delete_vertex", cIGraph_delete_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); /* in cIGraph_basic_properties.c */

View File

@ -14,7 +14,6 @@ igraph_integer_t cIGraph_get_vertex_id(VALUE graph, VALUE v);
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 cIGraph_include(VALUE self, VALUE v);
VALUE cIGraph_create_derived_graph(VALUE old_graph, igraph_t *new_graph);
//IGraph allocation, destruction and intialization
void Init_igraph(void);
@ -57,6 +56,7 @@ VALUE cIGraph_add_vertices (VALUE self, VALUE vs);
VALUE cIGraph_delete_edge (VALUE self, VALUE from, VALUE to);
VALUE cIGraph_delete_edges (VALUE self, VALUE edges);
VALUE cIGraph_delete_vertices(VALUE self, VALUE vs);
VALUE cIGraph_delete_vertex (VALUE self, VALUE v);
VALUE cIGraph_add_vertex (VALUE self, VALUE v);
//Basic properties

View File

@ -247,3 +247,25 @@ VALUE cIGraph_delete_edge(VALUE self, VALUE from, VALUE to){
return Qnil;
}
/* call-seq:
* graph.delete_vertex(v)
*
* Delete the vertex specified.
*/
VALUE cIGraph_delete_vertex(VALUE self, VALUE v){
igraph_t *graph;
igraph_vs_t vs;
Data_Get_Struct(self, igraph_t, graph);
igraph_vs_1(&vs, cIGraph_get_vertex_id(self,v));
igraph_delete_vertices(graph,vs);
igraph_vs_destroy(&vs);
return Qnil;
}

View File

@ -78,6 +78,17 @@ void cIGraph_attribute_destroy(igraph_t *graph) {
/* Copying */
int cIGraph_attribute_copy(igraph_t *to, const igraph_t *from) {
VALUE vertex_array = ((VALUE*)from->attr)[0];
VALUE edge_array = ((VALUE*)from->attr)[1];
VALUE* attrs = (VALUE*)calloc(2, sizeof(VALUE));
attrs[0] = rb_ary_dup(vertex_array);
attrs[1] = rb_ary_dup(edge_array);
to->attr = attrs;
return IGRAPH_SUCCESS;
}
@ -101,6 +112,24 @@ void cIGraph_attribute_delete_vertices(igraph_t *graph,
const igraph_vector_t *eidx,
const igraph_vector_t *vidx) {
int i;
VALUE vertex_array = ((VALUE*)graph->attr)[0];
VALUE edge_array = ((VALUE*)graph->attr)[1];
VALUE n_v_ary = rb_ary_new();
VALUE n_e_ary = rb_ary_new();
for(i=0;i<igraph_vector_size(vidx);i++){
if(VECTOR(*vidx)[i] != 0)
rb_ary_store(n_v_ary,VECTOR(*vidx)[i]-1,rb_ary_entry(vertex_array,i));
}
for(i=0;i<igraph_vector_size(eidx);i++){
if(VECTOR(*eidx)[i] != 0)
rb_ary_store(n_e_ary,VECTOR(*eidx)[i]-1,rb_ary_entry(edge_array,i));
}
((VALUE*)graph->attr)[0] = n_v_ary;
((VALUE*)graph->attr)[1] = n_e_ary;
return;
}
@ -124,6 +153,18 @@ int cIGraph_attribute_add_edges(igraph_t *graph,
/* Deleting edges */
void cIGraph_attribute_delete_edges(igraph_t *graph, const igraph_vector_t *idx) {
int i;
VALUE edge_array = ((VALUE*)graph->attr)[1];
VALUE n_e_ary = rb_ary_new();
for(i=0;i<igraph_vector_size(idx);i++){
if(VECTOR(*idx)[i] != 0)
rb_ary_store(n_e_ary,VECTOR(*idx)[i]-1,rb_ary_entry(edge_array,i));
}
((VALUE*)graph->attr)[1] = n_e_ary;
return;
}

View File

@ -13,9 +13,11 @@ igraph_integer_t cIGraph_get_vertex_id(VALUE graph, VALUE v){
idx = rb_funcall(v_ary,rb_intern("index"),1,v);
if(idx)
if(idx != Qnil)
return NUM2INT(idx);
rb_raise(cIGraphError, "Unable to find vertex\n");
return -1;
}

View File

@ -118,12 +118,14 @@ VALUE cIGraph_neighborhood(VALUE self, VALUE from, VALUE order, VALUE mode){
VALUE cIGraph_neighborhood_graphs(VALUE self, VALUE from, VALUE order, VALUE mode){
igraph_t *graph;
igraph_t *n_graph;
igraph_vs_t vids;
igraph_vector_t vidv;
igraph_neimode_t pmode = NUM2INT(mode);
igraph_vector_ptr_t res;
int i;
VALUE n_graph_obj;
VALUE result = rb_ary_new();
Data_Get_Struct(self, igraph_t, graph);
@ -138,7 +140,9 @@ VALUE cIGraph_neighborhood_graphs(VALUE self, VALUE from, VALUE order, VALUE mod
igraph_neighborhood_graphs(graph,&res,vids,NUM2INT(order),pmode);
for(i=0; i<igraph_vector_ptr_size(&res); i++){
rb_ary_push(result,cIGraph_create_derived_graph(self,VECTOR(res)[i]));
n_graph = VECTOR(res)[i];
n_graph_obj = Data_Wrap_Struct(cIGraph, 0, cIGraph_free, n_graph);
rb_ary_push(result,n_graph_obj);
}
igraph_vector_destroy(&vidv);

View File

@ -1,62 +1,22 @@
require 'igraph'
require 'kgml'
require 'gratr/import'
require 'benchmark'
xmlfiles = Dir.glob(ARGV[0])
pathway =
DirectedBipartiteMetabolicPathway.new(File.open(xmlfiles.shift).read)
pathway = xmlfiles.inject(pathway){|p,file|
p + DirectedBipartiteMetabolicPathway.new(File.open(file).read)
}
igraph = IGraph.new([],0,true);
pathway.reactions.each do |reaction|
reaction_name = reaction.name.gsub(/rn:/,'')
unless igraph.include?(reaction_name)
igraph.add_vertices([reaction_name])
end
reaction.substrates.each do |s_name|
s_name.gsub!(/cpd:/,'')
unless igraph.include?(s_name)
igraph.add_vertices([s_name])
end
igraph.add_edges([s_name,reaction_name])
if reaction.type == 'reversible'
igraph.add_edges([reaction_name,s_name])
end
end
reaction.products.each do |p_name|
p_name.gsub!(/cpd:/,'')
unless igraph.include?(p_name)
igraph.add_vertices([p_name])
end
igraph.add_edges([reaction_name,p_name])
if reaction.type == 'reversible'
igraph.add_edges([p_name,reaction_name])
end
end
end
gratr_g = Digraph[1,2,2,3,3,4]
igraph_g = IGraph.new([1,2,2,3,3,4])
graph_g =
include Benchmark
graph = pathway.graph
bm(6) do |x|
x.report("igraph"){
100.times{
igraph.get_shortest_paths("R02740",["C00074"])
50000.times{
igraph_g.topological_sorting(IGraph::OUT)
}
}
x.report("hashgraph"){
100.times{
h = {}
graph.dijkstra_shortest_paths({
:root => "R02740",
:target => "C00074",
:predecessor => h
})
graph.route("C00074",h)
x.report("gratr"){
50000.times{
gratr_g.topsort
}
}
end

View File

@ -46,4 +46,41 @@ class TestGraph < Test::Unit::TestCase
assert_equal [0], graph.degree(['E'],IGraph::ALL,true)
end
def test_delete_vertex
graph = IGraph.new(['A','B','C','D'],true,[1,2])
assert_nothing_raised do
graph.delete_vertex('A')
end
assert_equal false, graph.include?('A')
assert_equal 3, graph.vcount
assert_equal 1, graph.ecount
end
def test_delete_edge
graph = IGraph.new(['A','B','C','D'],true)
assert_equal true, graph.are_connected?('A','B')
assert_nothing_raised do
graph.delete_edge('A','B')
end
assert_equal false, graph.are_connected?('A','B')
end
def test_delete_edge_attr
graph = IGraph.new(['A','B','C','D'],true,[1,2])
assert_equal 1, graph['A','B']
assert_nothing_raised do
graph.delete_edge('A','B')
end
assert_equal false, graph.are_connected?('A','B')
assert_equal 2, graph['C','D']
end
def test_delete_missing_edge
graph = IGraph.new(['A','B','C','D'],true)
assert_equal true, graph.are_connected?('A','B')
assert_raises(IGraphError) do
graph.delete_edge('A','C')
end
end
end

View File

@ -3,7 +3,7 @@ require 'igraph'
class TestGraph < Test::Unit::TestCase
def test_are_connected
graph = IGraph.new(['A','B','C','D'],true)
graph = IGraph.new(['A','B','B','C','C','D'],true)
assert graph.are_connected('A','B')
assert !(graph.are_connected('A','C'))
end

View File

@ -13,9 +13,9 @@ 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::ALL)
m = graph.get_shortest_paths('A',['B'],IGraph::ALL)
assert_equal ['A','B'], m[0]
assert_equal [], m[1]
#assert_equal [], m[1]
end
def test_get_all_shortest_paths

View File

@ -13,4 +13,17 @@ class TestGraph < Test::Unit::TestCase
assert_equal [['A','B']], graph.neighborhood(['A'],1,IGraph::ALL)
assert_equal [['A','B','C']], graph.neighborhood(['A'],2,IGraph::ALL)
end
def test_neighborhood_graph
graph = IGraph.new(['A','B','B','C','C','D'],true,[1,2,3])
assert_instance_of IGraph, graph.neighbourhood_graphs(['A'],0,IGraph::ALL)[0]
assert_equal ['A'],
graph.neighbourhood_graphs(['A'],0,IGraph::ALL)[0].to_a
assert_equal ['A','B'],
graph.neighbourhood_graphs(['A'],1,IGraph::ALL)[0].to_a
assert_equal 1, graph.neighbourhood_graphs(['A'],1,IGraph::ALL)[0]['A','B']
assert_equal ['A','B','C'],
graph.neighbourhood_graphs(['A'],2,IGraph::ALL)[0].to_a
assert_equal 2, graph.neighbourhood_graphs(['A'],2,IGraph::ALL)[0]['B','C']
end
end

View File

@ -9,6 +9,9 @@ require 'tc_selectors'
require 'tc_add_delete'
require 'tc_basic_query'
require 'tc_basic_properties'
require 'tc_copy'
require 'tc_error_handling'
require 'tc_file_read_write'
require 'tc_shortest_paths'
require 'tc_topological_sort'
require 'tc_vertex_neighbourhood'