This commit is contained in:
alexgutteridge 2007-08-15 06:01:35 +00:00
parent f475b5f72b
commit d5deff9280
6 changed files with 150 additions and 48 deletions

View File

@ -188,6 +188,9 @@ void Init_igraph(){
rb_define_const(cIGraph, "ALL", INT2NUM(3));
rb_define_const(cIGraph, "TOTAL", INT2NUM(4));
rb_define_const(cIGraph, "WEAK", INT2NUM(1));
rb_define_const(cIGraph, "STRONG", INT2NUM(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", "[]");
@ -245,6 +248,9 @@ void Init_igraph(){
rb_define_alias (cIGraph, "neighborhood_graphs", "neighbourhood_graphs");
rb_define_method(cIGraph, "subcomponent", cIGraph_subcomponent, 2); /* in cIGraph_components.c */
rb_define_method(cIGraph, "subgraph", cIGraph_subgraph, 1); /* in cIGraph_components.c */
rb_define_method(cIGraph, "clusters", cIGraph_clusters, 1); /* in cIGraph_components.c */
rb_define_method(cIGraph, "decompose", cIGraph_decompose, -1); /* in cIGraph_decompose.c */
rb_define_method(cIGraph, "topological_sorting", cIGraph_topological_sorting, 1); /* in cIGraph_topological_sort.c */

View File

@ -86,6 +86,12 @@ VALUE cIGraph_neighborhood_size (VALUE self, VALUE from, VALUE order, VALUE mod
VALUE cIGraph_neighborhood (VALUE self, VALUE from, VALUE order, VALUE mode);
VALUE cIGraph_neighborhood_graphs(VALUE self, VALUE from, VALUE order, VALUE mode);
//Component functions
VALUE cIGraph_subcomponent(VALUE self, VALUE v, VALUE mode);
VALUE cIGraph_subgraph (VALUE self, VALUE vs);
VALUE cIGraph_clusters (VALUE self, VALUE mode);
VALUE cIGraph_decompose(int argc, VALUE *argv, VALUE self);
//Topological sorting
VALUE cIGraph_topological_sorting(VALUE self, VALUE mode);

View File

@ -12,7 +12,7 @@
* IGraph::ALL the graph is considered as an undirected graph. Note that
* this is not the same as the union of the previous two.
*/
VALUE cIgraph_subcomponent(VALUE self, VALUE v, VALUE mode){
VALUE cIGraph_subcomponent(VALUE self, VALUE v, VALUE mode){
igraph_t *graph;
igraph_neimode_t pmode = NUM2INT(mode);
@ -24,7 +24,7 @@ VALUE cIgraph_subcomponent(VALUE self, VALUE v, VALUE mode){
Data_Get_Struct(self, igraph_t, graph);
igraph_subcomponent(graph, &neis, cIGraph_get_vertex_id(self,from), pmode);
igraph_subcomponent(graph, &neis, cIGraph_get_vertex_id(self,v), pmode);
for(i=0;i<igraph_vector_size(&neis);i++){
rb_ary_push(component,cIGraph_get_vertex_object(self,VECTOR(neis)[i]));
@ -35,3 +35,120 @@ VALUE cIgraph_subcomponent(VALUE self, VALUE v, VALUE mode){
return component;
}
/* call-seq:
* graph.subgraph(vs) -> IGraph
*
* Returns an IGraph object containing the vertices defined in the Array vs.
*/
VALUE cIGraph_subgraph(VALUE self, VALUE vs){
igraph_t *graph;
igraph_t *n_graph = malloc(sizeof(igraph_t));
igraph_vs_t vids;
igraph_vector_t vidv;
VALUE n_graph_obj;
Data_Get_Struct(self, igraph_t, graph);
//Convert an array of vertices to a vector of vertex ids
cIGraph_vertex_arr_to_id_vec(self,vs,&vidv);
//create vertex selector from the vecotr of ids
igraph_vs_vector(&vids,&vidv);
igraph_subgraph(graph,n_graph,vids);
n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph);
igraph_vector_destroy(&vidv);
igraph_vs_destroy(&vids);
return n_graph_obj;
}
/* call-seq:
* graph.clusters(mode) -> Array
*
* Calculates the (weakly or strongly) connected components in a graph.
* Returns an Array of Arrays of vertices. Each sub-Array is a graph component
*/
VALUE cIGraph_clusters(VALUE self, VALUE mode){
igraph_t *graph;
igraph_vector_t membership;
igraph_integer_t no;
VALUE components;
VALUE v,c;
int i;
igraph_vector_init_int(&membership,0);
Data_Get_Struct(self, igraph_t, graph);
igraph_clusters(graph, &membership, NULL, &no, NUM2INT(mode));
components = rb_ary_new();
for(i=0;i<no;i++){
rb_ary_push(components,rb_ary_new());
}
for(i=0;i<igraph_vector_size(&membership);i++){
v = cIGraph_get_vertex_object(self, i);
c = rb_ary_entry(components,VECTOR(membership)[i]);
rb_ary_push(c,v);
}
igraph_vector_destroy(&membership);
return components;
}
/* call-seq:
* graph.decompose(mode,maxcomp=-1,minelem=1) -> Array
*
* Create separate graph for each component of a graph. Returns an Array
* of new IGraph object. mode specifies whether weakly and strongly connected
* components are returned. Right now only the former is implemented. maxcomp
* limits the number of components returned. Leave at the default -1 to return
* all components. minelements specifies the minimum number of vertices a
* component should contain before it is returned. Default 1 returns all
* components.
*/
VALUE cIGraph_decompose(int argc, VALUE *argv, VALUE self){
igraph_t *graph;
igraph_t *n_graph;
igraph_vector_ptr_t components;
VALUE mode,maxcomp, minelem, components_a;
VALUE n_graph_obj;
int i;
rb_scan_args(argc,argv,"12", &mode, &maxcomp, &minelem);
if(maxcomp == Qnil)
maxcomp = INT2NUM(-1);
if(minelem == Qnil)
minelem = INT2NUM(1);
igraph_vector_ptr_init(&components,0);
Data_Get_Struct(self, igraph_t, graph);
igraph_decompose(graph, &components, NUM2INT(mode), NUM2INT(maxcomp), NUM2INT(minelem));
components_a = rb_ary_new();
for(i=0; i<igraph_vector_ptr_size(&components); i++){
n_graph = VECTOR(components)[i];
n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph);
rb_ary_push(components_a,n_graph_obj);
}
igraph_vector_ptr_destroy(&components);
return components_a;
}

View File

@ -141,7 +141,7 @@ VALUE cIGraph_neighborhood_graphs(VALUE self, VALUE from, VALUE order, VALUE mod
for(i=0; i<igraph_vector_ptr_size(&res); i++){
n_graph = VECTOR(res)[i];
n_graph_obj = Data_Wrap_Struct(cIGraph, 0, cIGraph_free, n_graph);
n_graph_obj = Data_Wrap_Struct(cIGraph, cIGraph_mark, cIGraph_free, n_graph);
rb_ary_push(result,n_graph_obj);
}

View File

@ -2,53 +2,24 @@ require 'test/unit'
require 'igraph'
class TestGraph < Test::Unit::TestCase
def test_graph_size
assert_equal 4, IGraph.new([1,2,3,4],true).vcount
assert_equal 2, IGraph.new([1,2,3,4],true).ecount
def test_subcomponent
g = IGraph.new([1,2,3,4])
assert_equal [1,2], g.subcomponent(1,IGraph::ALL)
end
def test_eid_get_edge
assert_nothing_raised do
IGraph.new(['A','B','C','D'],true).get_eid('A','B')
end
graph = IGraph.new(['A','B','C','D'],true)
eid1 = graph.get_eid('A','B')
eid2 = graph.get_eid('C','D')
assert_equal ['A','B'], graph.edge(eid1)
assert_equal ['C','D'], graph.edge(eid2);
assert_not_equal eid1,eid2
def test_subgraph
g = IGraph.new([1,2,3,4])
h = g.subgraph([1,2])
assert_equal 2, h.vcount
assert_equal [1,2], h.vertices
end
def test_neighbours
assert_nothing_raised do
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::ALL)
assert_equal ['D'], graph.neighbors('C',IGraph::ALL)
def test_clusters
g = IGraph.new([1,2,3,4])
assert_equal 2, g.clusters(IGraph::WEAK).length
assert_equal [1,2], g.clusters(IGraph::WEAK)[0]
end
def test_adjacent
assert_nothing_raised do
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::ALL)[0]
assert_equal eid1, eid2
end
def test_directed
assert IGraph.new(['A','B','C','D'],true).is_directed?
assert !(IGraph.new(['A','B','C','D'],false).is_directed?)
end
def test_degree
graph = IGraph.new(['A','B','C','D'],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
def test_decompose
g = IGraph.new([1,2,3,4])
assert_equal 2, g.decompose(IGraph::WEAK).length
assert_equal [1,2], g.decompose(IGraph::WEAK)[0].vertices
end
end

View File

@ -9,6 +9,8 @@ require 'tc_selectors'
require 'tc_add_delete'
require 'tc_basic_query'
require 'tc_basic_properties'
require 'tc_centrality'
require 'tc_components'
require 'tc_copy'
require 'tc_error_handling'
require 'tc_file_read_write'