git-svn-id: http://igraph.rubyforge.org/svn/trunk@23 71f48855-0bbf-4aa5-930d-4df415e86613
This commit is contained in:
parent
61826fa8cd
commit
f8e5537bef
11
History.txt
11
History.txt
|
@ -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
|
|
@ -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
|
||||
|
|
19
README.txt
19
README.txt
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
|
|
Loading…
Reference in New Issue