From 5d14773ec385efd43111de779579c0d540dc9d94 Mon Sep 17 00:00:00 2001 From: Hamlet Date: Wed, 10 Nov 2010 05:21:49 +0100 Subject: [PATCH 1/6] added weight support for dijstra get shortes and for fast greedy algorithm --- Rakefile.rb | 14 +++++++------- ext/cIGraph.h | 3 ++- ext/cIGraph_community.c | 12 +++++++++--- ext/cIGraph_dijkstra.c | 15 ++++++++++++--- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/Rakefile.rb b/Rakefile.rb index bd631b9..6ff562d 100644 --- a/Rakefile.rb +++ b/Rakefile.rb @@ -11,20 +11,20 @@ class IGraph #rescue RuntimeError #end -hoe = Hoe.new("igraph",IGraph::VERSION) do |p| - +hoe = Hoe.spec("igraph") do |p| + p.author = "Alex Gutteridge" p.email = "ag357@cam.ac.uk" 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] p.changes = p.paragraphs_of("History.txt",0..1).join("\n\n") - + p.clean_globs = ["ext/*.o","ext/*.so","ext/Makefile","ext/mkmf.log","**/*~","email.txt","manual.{aux,log,out,toc,pdf}"] - - p.rdoc_pattern = /(^ext\/.*\.c$|^README|^History|^License)/ - + + #p.rdoc_pattern = /(^ext\/.*\.c$|^README|^History|^License)/ + p.spec_extras = { :extensions => ['ext/extconf.rb'], :require_paths => ['test'], diff --git a/ext/cIGraph.h b/ext/cIGraph.h index 093fa47..493c2a6 100644 --- a/ext/cIGraph.h +++ b/ext/cIGraph.h @@ -117,6 +117,7 @@ VALUE cIGraph_diameter (VALUE self, VALUE directed, VALUE unconn); VALUE cIGraph_girth (VALUE self); VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VALUE mode); +VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE weights, VALUE mode); int igraph_dijkstra_shortest_paths(const igraph_t *graph, igraph_matrix_t *res, const igraph_vs_t from, @@ -313,7 +314,7 @@ VALUE cIGraph_community_edge_betweenness (VALUE self, VALUE directed); VALUE cIGraph_community_eb_get_merges (VALUE self, VALUE edges); -VALUE cIGraph_community_fastgreedy (VALUE self); +VALUE cIGraph_community_fastgreedy (VALUE self,VALUE weights); //Attributes int cIGraph_attribute_init(igraph_t *graph, diff --git a/ext/cIGraph_community.c b/ext/cIGraph_community.c index 4ef183b..fdb6702 100644 --- a/ext/cIGraph_community.c +++ b/ext/cIGraph_community.c @@ -625,10 +625,10 @@ VALUE cIGraph_community_eb_get_merges(VALUE self, VALUE edges){ * */ -VALUE cIGraph_community_fastgreedy(VALUE self){ +VALUE cIGraph_community_fastgreedy(VALUE self, VALUE weights){ igraph_t *graph; - + igraph_vector_t weights_vec; igraph_vector_t modularity; igraph_matrix_t *merges = malloc(sizeof(igraph_matrix_t)); @@ -640,8 +640,13 @@ VALUE cIGraph_community_fastgreedy(VALUE self){ igraph_matrix_init(merges,0,0); igraph_vector_init(&modularity,0); + igraph_vector_init(&weights_vec,RARRAY_LEN(weights)); + + for(i=0;i 0 ? &weights_vec : NULL, merges,&modularity); modularity_a = rb_ary_new(); @@ -655,6 +660,7 @@ VALUE cIGraph_community_fastgreedy(VALUE self){ modularity_a); igraph_vector_destroy(&modularity); + igraph_vector_destroy(&weights_vec); return res; diff --git a/ext/cIGraph_dijkstra.c b/ext/cIGraph_dijkstra.c index 90f7d99..484272d 100644 --- a/ext/cIGraph_dijkstra.c +++ b/ext/cIGraph_dijkstra.c @@ -64,7 +64,7 @@ VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VAL igraph_vector_destroy(&vidv); igraph_matrix_destroy(&res); igraph_vs_destroy(&vids); - + igraph_vector_destroy(&wghts); return matrix; } @@ -80,13 +80,14 @@ VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VAL * calculated. IGraph::ALL the directed graph is considered as an undirected * one for the computation. */ -VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE mode){ +VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE weights, VALUE mode){ igraph_t *graph; igraph_integer_t from_vid; igraph_vs_t to_vids; igraph_vector_t to_vidv; + igraph_vector_t wghts; igraph_neimode_t pmode = NUM2INT(mode); @@ -111,6 +112,12 @@ VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALU igraph_vector_ptr_push_back(&res,path_v); } + igraph_vector_init(&wghts,RARRAY_LEN(weights)); + + for(i=0;i 0 ? &wghts : NULL,pmode); for(i=0; i Date: Wed, 10 Nov 2010 10:31:48 +0100 Subject: [PATCH 2/6] added test and refactored dijkstra --- .idea/dictionaries/hamlet.xml | 3 ++ .idea/encodings.xml | 5 +++ .idea/igraph2.iml | 18 +++++++++ .idea/misc.xml | 8 ++++ .idea/modules.xml | 9 +++++ .idea/vcs.xml | 8 ++++ ext/cIGraph.c | 3 +- ext/cIGraph_dijkstra.c | 75 ++++++++++++++++++++++++++++++++++- test/tc_dijkstra.rb | 12 ++++++ 9 files changed, 139 insertions(+), 2 deletions(-) create mode 100644 .idea/dictionaries/hamlet.xml create mode 100644 .idea/encodings.xml create mode 100644 .idea/igraph2.iml create mode 100644 .idea/misc.xml create mode 100644 .idea/modules.xml create mode 100644 .idea/vcs.xml diff --git a/.idea/dictionaries/hamlet.xml b/.idea/dictionaries/hamlet.xml new file mode 100644 index 0000000..71ff7a5 --- /dev/null +++ b/.idea/dictionaries/hamlet.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..e206d70 --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/.idea/igraph2.iml b/.idea/igraph2.iml new file mode 100644 index 0000000..af64c60 --- /dev/null +++ b/.idea/igraph2.iml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..f26f657 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..35ce8ac --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..9d32e50 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/ext/cIGraph.c b/ext/cIGraph.c index 695e7f6..043ecc5 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -340,6 +340,7 @@ void Init_igraph(){ rb_define_method(cIGraph_shortestpaths, "girth", cIGraph_girth, 0); /* in cIGraph_shortest_paths.c */ rb_define_method(cIGraph_shortestpaths, "dijkstra_shortest_paths", cIGraph_dijkstra_shortest_paths, 3); /* in cIGraph_dijkstra.c */ + rb_define_method(cIGraph_shortestpaths, "get_dijkstra_shortest_paths", cIGraph_get_dijkstra_shortest_paths, 4); /* in cIGraph_dijkstra.c */ /* Functions for querying the neighborhood of vertices */ cIGraph_neighborhoodm = rb_define_module_under(cIGraph, "Neighborhood"); @@ -554,7 +555,7 @@ void Init_igraph(){ rb_define_method(cIGraph_community, "community_leading_eigenvector_step", cIGraph_community_leading_eigenvector_step, 2); /* in cIGraph_community.c */ rb_define_method(cIGraph_community, "community_walktrap", cIGraph_community_walktrap, 2); /* in cIGraph_community.c */ rb_define_method(cIGraph_community, "community_edge_betweenness", cIGraph_community_edge_betweenness, 1); /* in cIGraph_community.c */ rb_define_method(cIGraph_community, "community_eb_get_merges", cIGraph_community_eb_get_merges, 1); /* in cIGraph_community.c */ - rb_define_method(cIGraph_community, "community_fastgreedy", cIGraph_community_fastgreedy, 0); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_fastgreedy", cIGraph_community_fastgreedy, 1); /* in cIGraph_community.c */ rb_define_const(cIGraph, "VERSION", rb_str_new2("0.9.1")); diff --git a/ext/cIGraph_dijkstra.c b/ext/cIGraph_dijkstra.c index 484272d..a4e539f 100644 --- a/ext/cIGraph_dijkstra.c +++ b/ext/cIGraph_dijkstra.c @@ -82,7 +82,7 @@ VALUE cIGraph_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE weights, VAL */ VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALUE weights, VALUE mode){ - igraph_t *graph; + igraph_t *graph; igraph_integer_t from_vid; igraph_vs_t to_vids; @@ -151,6 +151,79 @@ VALUE cIGraph_get_dijkstra_shortest_paths(VALUE self, VALUE from, VALUE to, VALU return matrix; + /* + igraph_t *graph; + + igraph_integer_t from_vid; + igraph_vs_t to_vids; + igraph_vector_t to_vidv; + igraph_vector_t wghts; + + igraph_neimode_t pmode = NUM2INT(mode); + + igraph_vector_ptr_t res; + igraph_vector_t *path_v; + + int i; + int j; + VALUE path; + VALUE matrix = rb_ary_new(); + int n_paths = 0; + + Data_Get_Struct(self, igraph_t, graph); + + n_paths = RARRAY_LEN(to); + + //vector to hold the results of the calculations + igraph_vector_ptr_init(&res,0); + + for(i=0;i 0 ? &wghts : NULL,pmode); + + for(i=0; i Date: Mon, 15 Nov 2010 22:20:37 +0100 Subject: [PATCH 3/6] fix gemspec --- igraph.gemspec | 1 - 1 file changed, 1 deletion(-) diff --git a/igraph.gemspec b/igraph.gemspec index 0d0a145..ab6ff42 100644 --- a/igraph.gemspec +++ b/igraph.gemspec @@ -1,4 +1,3 @@ -(in /home/ag357/Projects/igraph) # -*- encoding: utf-8 -*- Gem::Specification.new do |s| From 91fd079def0f554bcd82e835d51967e0152eebf6 Mon Sep 17 00:00:00 2001 From: Hamlet Date: Wed, 24 Nov 2010 18:46:05 +0100 Subject: [PATCH 4/6] fixed random walks with weights --- ext/cIGraph_community.c | 8 ++-- test/tc_community.rb | 88 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 90 insertions(+), 6 deletions(-) diff --git a/ext/cIGraph_community.c b/ext/cIGraph_community.c index fdb6702..a32a466 100644 --- a/ext/cIGraph_community.c +++ b/ext/cIGraph_community.c @@ -43,7 +43,7 @@ VALUE cIGraph_modularity(VALUE self, VALUE groups){ } /* call-seq: - * graph.community_to_membership(merge,steps) -> Array + * graph.community_to_membership(merge,steps,nodes) -> Array * * Create membership vector from community structure dendrogram This function * creates a membership vector from a community structure dendrogram. @@ -458,10 +458,10 @@ igraph_arpack_options_init(&arpack_opt); * */ + VALUE cIGraph_community_walktrap(VALUE self, VALUE weights, VALUE steps){ igraph_t *graph; - igraph_vector_t weights_vec; igraph_vector_t modularity; igraph_matrix_t *merges = malloc(sizeof(igraph_matrix_t)); @@ -473,8 +473,8 @@ VALUE cIGraph_community_walktrap(VALUE self, VALUE weights, VALUE steps){ Data_Get_Struct(self, igraph_t, graph); igraph_matrix_init(merges,0,0); - igraph_vector_init(&weights_vec,0); igraph_vector_init(&modularity,0); + igraph_vector_init(&weights_vec,RARRAY_LEN(weights)); for(i=0;i Array + * graph.community_fastgreedy(weights) -> Array * * Finding community structure by greedy optimization of modularity. * This function implements the fast greedy modularity optimization algorithm diff --git a/test/tc_community.rb b/test/tc_community.rb index 2bf5615..523f955 100644 --- a/test/tc_community.rb +++ b/test/tc_community.rb @@ -11,7 +11,7 @@ def test_spinglass groups,mod,temp = g.community_spinglass([],25,false,1,0.01,0.99,IGraph::SPINCOMM_UPDATE_SIMPLE,1.0) assert_in_delta 0.25, mod, 0.15 assert_in_delta 0.200, temp, 0.100 - assert_equal [['A','B','C','D','E','F']], groups + assert_equal [['A','B','C'],['D','E','F']], groups.sort commun,coh,adh = g.community_spinglass_single([],'A',25,IGraph::SPINCOMM_UPDATE_SIMPLE,1.0) assert_in_delta 1.25, coh, 0.001 assert_in_delta(-2.5, adh, 0.100) @@ -63,10 +63,94 @@ def test_comm_edge_betweenness def test_fastgreedy g = IGraph.new(['A','B','B','C','A','C','C','D','D','E','E','F','D','F'],false) - merges,mod = g.community_fastgreedy + merges,mod = g.community_fastgreedy([]) groups = g.community_to_membership(merges,4,6) assert_equal [['A','B','C'],['D','E','F']], groups.sort assert_in_delta 0.19, mod[3], 0.1 end + + + def test_extend_weights + graph = IGraph.new(['A1','B1','A1','C1','B1','C1','C1','D1',\ + 'A2','B2','A2','C2','A2','D2','B2','C2','B2','D2','C2','D2','D2','E2',\ + 'A3','B3','A3','C3','A3','D3','A3','E3','B3','C3','B3','D3','B3','E3','C3','D3','C3','E3','D3','E3',\ + 'A1','A2','B2','B3'],false) + + weights = [5,7,7,5,\ + 6,6,5,7,5,6,8,\ + 8,4,3,5,4,6,7,8,3,7,\ + 3,3] + merges,mod = graph.community_walktrap(weights,50) + max_idx = mod.index(mod.max) + res = graph.community_to_membership(merges,max_idx,graph.vcount()).sort + assert_equal [["A1", "B1", "C1", "D1"], ["A2", "B2", "C2", "D2", "E2"], ["A3", "B3", "C3", "D3", "E3"]], res + + merges,mod = graph.community_walktrap([],50) + max_idx = mod.index(mod.max) + res = graph.community_to_membership(merges,max_idx,graph.vcount()).sort + assert_equal [["A1", "B1", "C1", "D1"], ["A2", "B2", "C2", "D2", "E2"], ["A3", "B3", "C3", "D3", "E3"]], res + + end + + def test_extend_fastgreedy + graph = IGraph.new(['A1','B1','A1','C1','B1','C1','C1','D1',\ + 'A2','B2','A2','C2','A2','D2','B2','C2','B2','D2','C2','D2','D2','E2',\ + 'A3','B3','A3','C3','A3','D3','A3','E3','B3','C3','B3','D3','B3','E3','C3','D3','C3','E3','D3','E3',\ + 'A1','A2','B2','B3'],false) + + weights = [5,7,7,5,\ + 6,6,5,7,5,6,8,\ + 8,4,3,5,4,6,7,8,3,7,\ + 3,3] + + merges,mod = graph.community_fastgreedy(weights) + max_idx = mod.index(mod.max) + res = graph.community_to_membership(merges,max_idx,graph.vcount()).sort + assert_equal [["A1", "B1", "C1", "D1"], ["A2", "B2", "C2", "D2", "E2"], ["A3", "B3", "C3", "D3", "E3"]], res + + merges,mod = graph.community_fastgreedy([]) + max_idx = mod.index(mod.max) + res = graph.community_to_membership(merges,max_idx,graph.vcount()).sort + assert_equal [["A1", "B1", "C1", "D1"], ["A2", "B2", "C2", "D2", "E2"], ["A3", "B3", "C3", "D3", "E3"]], res + + + end + + def test_extend_betweenness + graph = IGraph.new(['A1','B1','A1','C1','B1','C1','C1','D1',\ + 'A2','B2','A2','C2','A2','D2','B2','C2','B2','D2','C2','D2','D2','E2',\ + 'A3','B3','A3','C3','A3','D3','A3','E3','B3','C3','B3','D3','B3','E3','C3','D3','C3','E3','D3','E3',\ + 'A1','A2','B2','B3'],false) + + weights = [5,7,7,5,\ + 6,6,5,7,5,6,8,\ + 8,4,3,5,4,6,7,8,3,7,\ + 3,3] + + + merges,result,edge_betw,bridges = graph.community_edge_betweenness(false) + + #max_idx = mod.index(mod.max) + res = graph.community_to_membership(merges,11,graph.vcount()).sort + #puts graph.modularity(edge_betw).to_s + assert_equal [["A1", "B1", "C1", "D1"], ["A2", "B2", "C2", "D2", "E2"], ["A3", "B3", "C3", "D3", "E3"]], res + + end + + def test_extend_eigenvector + graph = IGraph.new(['A1','B1','A1','C1','B1','C1','C1','D1',\ + 'A2','B2','A2','C2','A2','D2','B2','C2','B2','D2','C2','D2','D2','E2',\ + 'A3','B3','A3','C3','A3','D3','A3','E3','B3','C3','B3','D3','B3','E3','C3','D3','C3','E3','D3','E3',\ + 'A1','A2','B2','B3'],false) + + weights = [5,7,7,5,\ + 6,6,5,7,5,6,8,\ + 8,4,3,5,4,6,7,8,3,7,\ + 3,3] + + res = graph.community_leading_eigenvector(10)[0].sort + assert_equal [["A1", "B1", "C1", "D1"], ["A2", "B2", "C2", "D2", "E2"], ["A3", "B3", "C3", "D3", "E3"]], res + end + end From 18a20dc117c22f2f14b02b0402eb1ea886fb1eae Mon Sep 17 00:00:00 2001 From: Hamlet Date: Wed, 24 Nov 2010 21:53:52 +0100 Subject: [PATCH 5/6] added function for calling label propagation without the possibility to set initial status --- ext/cIGraph.c | 1 + ext/cIGraph.h | 1 + ext/cIGraph_community.c | 87 +++++++++++++++++++++++++++++++++++++++++ test/tc_community.rb | 17 +++++++- 4 files changed, 105 insertions(+), 1 deletion(-) diff --git a/ext/cIGraph.c b/ext/cIGraph.c index 043ecc5..43a869a 100644 --- a/ext/cIGraph.c +++ b/ext/cIGraph.c @@ -556,6 +556,7 @@ void Init_igraph(){ rb_define_method(cIGraph_community, "community_edge_betweenness", cIGraph_community_edge_betweenness, 1); /* in cIGraph_community.c */ rb_define_method(cIGraph_community, "community_eb_get_merges", cIGraph_community_eb_get_merges, 1); /* in cIGraph_community.c */ rb_define_method(cIGraph_community, "community_fastgreedy", cIGraph_community_fastgreedy, 1); /* in cIGraph_community.c */ + rb_define_method(cIGraph_community, "community_label_propagation", cIGraph_community_label_propagation, 1); /* in cIGraph_community.c */ rb_define_const(cIGraph, "VERSION", rb_str_new2("0.9.1")); diff --git a/ext/cIGraph.h b/ext/cIGraph.h index 493c2a6..7fd1302 100644 --- a/ext/cIGraph.h +++ b/ext/cIGraph.h @@ -315,6 +315,7 @@ VALUE cIGraph_community_edge_betweenness (VALUE self, VALUE cIGraph_community_eb_get_merges (VALUE self, VALUE edges); VALUE cIGraph_community_fastgreedy (VALUE self,VALUE weights); +VALUE cIGraph_community_label_propagation (VALUE self,VALUE weights); //Attributes int cIGraph_attribute_init(igraph_t *graph, diff --git a/ext/cIGraph_community.c b/ext/cIGraph_community.c index a32a466..69568a5 100644 --- a/ext/cIGraph_community.c +++ b/ext/cIGraph_community.c @@ -665,3 +665,90 @@ VALUE cIGraph_community_fastgreedy(VALUE self, VALUE weights){ return res; } + +/* call-seq: + * graph.community_label_propagation(weights) -> Array + * + Community detection based on label propagation This function implements the community detection method described in: + Raghavan, U.N. and Albert, R. and Kumara, S.: Near linear time algorithm to detect community structures in large-scale + networks. Phys Rev E 76, 036106. (2007). This version extends the original method by the ability to take edge weights + into consideration and also by allowing some labels to be fixed. + +Arguments: + +weights: + +The weight vector, it should contain a positive weight for all the edges + * + */ + +VALUE cIGraph_community_label_propagation(VALUE self, VALUE weights){ + + igraph_t *graph; + + igraph_vector_t membership; + igraph_vector_t weights_vec; + igraph_matrix_t *merges = malloc(sizeof(igraph_matrix_t)); + +igraph_arpack_options_t arpack_opt; +igraph_arpack_options_init(&arpack_opt); + + + int i,groupid,max_groupid; + + VALUE groups, group, res; + + Data_Get_Struct(self, igraph_t, graph); + + igraph_matrix_init(merges,0,0); + igraph_vector_init(&membership,0); + igraph_vector_init(&weights_vec,RARRAY_LEN(weights)); + + + for(i=0;i max_groupid) + max_groupid = VECTOR(membership)[i]; + } + + groups = rb_ary_new(); + for(i=0;i Date: Wed, 25 May 2011 15:33:16 +0200 Subject: [PATCH 6/6] label also with null weight --- ext/cIGraph_community.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 ext/cIGraph_community.c diff --git a/ext/cIGraph_community.c b/ext/cIGraph_community.c old mode 100644 new mode 100755 index 69568a5..854ce6b --- a/ext/cIGraph_community.c +++ b/ext/cIGraph_community.c @@ -712,7 +712,7 @@ igraph_arpack_options_init(&arpack_opt); igraph_community_label_propagation(graph, &membership, - &weights_vec, + igraph_vector_size(&weights_vec) > 0 ? &weights_vec : NULL, NULL, NULL);