louvian_ruby 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/lib/louvian.rb +61 -52
- metadata +1 -1
data/lib/louvian.rb
CHANGED
@@ -1,92 +1,97 @@
|
|
1
|
-
|
1
|
+
class Louvian
|
2
2
|
require 'louvian/community'
|
3
3
|
require 'louvian/graph'
|
4
4
|
|
5
5
|
MIN_INCREASE = 0.000001
|
6
6
|
|
7
7
|
|
8
|
-
|
9
|
-
|
8
|
+
# This method sets up the whole environemnt for calculations
|
9
|
+
#
|
10
|
+
# @param string [String] in the form of src dest (one edge per line)
|
11
|
+
#
|
12
|
+
def initialize tuples, directed
|
13
|
+
#list = string.split("\n").map {|line| line.split.map{|n| n.to_i}}
|
14
|
+
@graph = Graph.new tuples, directed, 0
|
15
|
+
@levels = [] # List of Graphs
|
10
16
|
end
|
11
17
|
|
12
|
-
def
|
13
|
-
|
18
|
+
def graph
|
19
|
+
@graph
|
14
20
|
end
|
15
21
|
|
16
|
-
def
|
17
|
-
|
22
|
+
def graph= value
|
23
|
+
@graph = value
|
18
24
|
end
|
19
25
|
|
20
|
-
def
|
21
|
-
|
26
|
+
def levels
|
27
|
+
@levels
|
22
28
|
end
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
def self.init_env string, directed
|
27
|
-
list = string.split("\n").map {|line| line.split.map{|n| n.to_i}}
|
28
|
-
@@graph = Graph.new list, directed, 0
|
29
|
-
@@levels = [] # List of Graphs
|
30
|
-
nil
|
29
|
+
|
30
|
+
def levels= value
|
31
|
+
@levels = value
|
31
32
|
end
|
32
33
|
|
33
|
-
def
|
34
|
+
def run
|
34
35
|
l = 0
|
35
|
-
|
36
|
-
puts "Level #{l}: Comms #{@@graph.communities.size}"
|
36
|
+
puts "Level #{l}: Comms #{@graph.communities.size}"
|
37
37
|
l +=1
|
38
38
|
|
39
39
|
while self.one_level
|
40
|
-
puts "Level #{l}: Comms #{
|
41
|
-
|
42
|
-
|
40
|
+
puts "Level #{l}: Comms #{@graph.communities.size}"
|
41
|
+
@levels << @graph
|
42
|
+
@graph = @graph.build_graph_from_comms
|
43
|
+
|
43
44
|
l+=1
|
44
45
|
end
|
46
|
+
self
|
45
47
|
end
|
46
48
|
|
47
|
-
def
|
48
|
-
|
49
|
-
|
49
|
+
def unfold_levels!
|
50
|
+
return false if @levels.size < 2
|
51
|
+
puts "levels count #{@levels.size}"
|
52
|
+
@levels[(1..-1)].each_with_index do |graph, i|
|
53
|
+
graph.expand! @levels[i]
|
50
54
|
end
|
55
|
+
true
|
51
56
|
end
|
52
57
|
|
53
|
-
def
|
54
|
-
|
58
|
+
def display_hierarchy
|
59
|
+
@levels.each do |graph|
|
55
60
|
puts "level #{graph.level}: Nodes #{graph.communities.count}"
|
56
61
|
end
|
57
|
-
|
62
|
+
nil
|
58
63
|
end
|
59
64
|
|
60
65
|
# This method iterates over the graph to optimze the modularity. Iterations
|
61
66
|
# stops when there are no possible moves anymore.
|
62
67
|
# @returns improvement [Boolean] indicates whether there was improvment or no
|
63
|
-
def
|
68
|
+
def one_level
|
64
69
|
improvement = false
|
65
70
|
nb_passes = 0
|
66
|
-
cur_mod =
|
71
|
+
cur_mod = @graph.modularity
|
67
72
|
new_mod = cur_mod
|
68
73
|
begin
|
69
74
|
#puts "Iterating"
|
70
|
-
#puts "modularity is #{
|
75
|
+
#puts "modularity is #{@graph.modularity}"
|
71
76
|
cur_mod = new_mod
|
72
77
|
nb_moves = 0
|
73
78
|
nb_passes += 1
|
74
|
-
|
75
|
-
#puts "\t#{
|
79
|
+
@graph.nodes.shuffle.each do |node|
|
80
|
+
#puts "\t#{@graph.n2c}"
|
76
81
|
#puts "\tconsidering node #{node}"
|
77
|
-
orig_community =
|
82
|
+
orig_community = @graph.get_community node
|
78
83
|
|
79
|
-
neighbour_communities =
|
84
|
+
neighbour_communities = @graph.get_neighbour_comms node
|
80
85
|
|
81
86
|
#puts "\tneihbours#{neighbour_communities.map {|i| i.id}} origin #{orig_community.id}"
|
82
|
-
|
87
|
+
@graph.remove_node node, orig_community
|
83
88
|
|
84
89
|
|
85
90
|
best_community = orig_community
|
86
91
|
max_gain = 0.0
|
87
92
|
|
88
93
|
neighbour_communities.each do |comm|
|
89
|
-
mod_gain =
|
94
|
+
mod_gain = @graph.modularity_gain node, comm
|
90
95
|
#puts "\t\tfor comm #{comm.id} mod increase is #{mod_gain}"
|
91
96
|
if mod_gain > max_gain
|
92
97
|
max_gain = mod_gain
|
@@ -99,20 +104,19 @@ module Louvian
|
|
99
104
|
#puts "\t\tbest comm #{best_community.id}"
|
100
105
|
end
|
101
106
|
|
102
|
-
|
107
|
+
@graph.insert_node node, best_community
|
103
108
|
|
104
|
-
|
109
|
+
@graph.garbage_collect orig_community
|
105
110
|
|
106
111
|
end
|
107
|
-
new_mod =
|
112
|
+
new_mod = @graph.modularity
|
108
113
|
#puts "modularity was #{cur_mod} and now #{new_mod}, moves #{nb_moves}"
|
109
114
|
end while nb_moves > 0 and new_mod - cur_mod >= MIN_INCREASE
|
110
115
|
return improvement
|
111
116
|
end
|
112
117
|
|
113
|
-
|
114
|
-
|
115
|
-
s='0 1 1
|
118
|
+
def self.example s=nil
|
119
|
+
s ||='0 1 1
|
116
120
|
0 8 1
|
117
121
|
1 3 1
|
118
122
|
1 4 1
|
@@ -124,14 +128,19 @@ module Louvian
|
|
124
128
|
4 7 1
|
125
129
|
5 6 1
|
126
130
|
5 7 1'
|
131
|
+
list = self.make_list_from_string s
|
132
|
+
|
133
|
+
l = Louvian.new(list, false)
|
134
|
+
#l.one_level
|
135
|
+
#ng = l.graph.build_graph_from_comms
|
136
|
+
#l.levels << l.graph
|
137
|
+
#l.graph = ng
|
138
|
+
l.run
|
139
|
+
return l
|
140
|
+
end
|
127
141
|
|
128
|
-
|
129
|
-
|
130
|
-
ng = Louvian.graph.build_graph_from_comms
|
131
|
-
Louvian.levels << Louvian.graph
|
132
|
-
Louvian.graph = ng
|
133
|
-
#L = Louvian
|
134
|
-
#Louvian.run
|
135
|
-
nil
|
142
|
+
def self.make_list_from_string s
|
143
|
+
list = (s.split("\n").map {|line| line.split.map{|n| n.to_i}})
|
136
144
|
end
|
145
|
+
|
137
146
|
end
|