rgraphum 0.0.1.alpha

Sign up to get free protection for your applications and to get access to all the features.
Files changed (106) hide show
  1. data/.gitignore +26 -0
  2. data/GLOSSARIES.md +108 -0
  3. data/GREMLIN.md +1398 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +22 -0
  6. data/README.md +136 -0
  7. data/Rakefile +16 -0
  8. data/bin/.irbrc +41 -0
  9. data/bin/rgraphum_console +61 -0
  10. data/bin/rgraphum_runner +57 -0
  11. data/examples/ba_model/make.rb +19 -0
  12. data/examples/ba_model/make_dummy_twitter_rt_data.rb +0 -0
  13. data/examples/basic/check_modularity.rb +27 -0
  14. data/examples/basic/make_graph.rb +12 -0
  15. data/examples/parser/dot.rb +28 -0
  16. data/examples/sis_model/lifegame.rb +161 -0
  17. data/graph_struct.jpg +0 -0
  18. data/lib/rgraphum/analyzer/linear_regression.rb +31 -0
  19. data/lib/rgraphum/analyzer/meme_tracker.rb +296 -0
  20. data/lib/rgraphum/analyzer/twitter/rt_at_mark.rb +45 -0
  21. data/lib/rgraphum/analyzer.rb +8 -0
  22. data/lib/rgraphum/cluster.rb +67 -0
  23. data/lib/rgraphum/communities.rb +65 -0
  24. data/lib/rgraphum/community.rb +86 -0
  25. data/lib/rgraphum/cosine_similarity_matrix.rb +40 -0
  26. data/lib/rgraphum/edge.rb +194 -0
  27. data/lib/rgraphum/edges.rb +161 -0
  28. data/lib/rgraphum/ext/cosine_similarity_matrix.rb +79 -0
  29. data/lib/rgraphum/ext/linear_regression.rb +22 -0
  30. data/lib/rgraphum/ext/tf_idf.rb +52 -0
  31. data/lib/rgraphum/graph/gremlin.rb +193 -0
  32. data/lib/rgraphum/graph/math/clustering_coefficient.rb +53 -0
  33. data/lib/rgraphum/graph/math/community_detection.rb +141 -0
  34. data/lib/rgraphum/graph/math/degree_distribution.rb +50 -0
  35. data/lib/rgraphum/graph/math/dijkstra.rb +331 -0
  36. data/lib/rgraphum/graph/math.rb +45 -0
  37. data/lib/rgraphum/graph.rb +267 -0
  38. data/lib/rgraphum/importer.rb +97 -0
  39. data/lib/rgraphum/marshal.rb +26 -0
  40. data/lib/rgraphum/motifs.rb +8 -0
  41. data/lib/rgraphum/parsers/flare.rb +42 -0
  42. data/lib/rgraphum/parsers/gephi.rb +193 -0
  43. data/lib/rgraphum/parsers/graphviz.rb +78 -0
  44. data/lib/rgraphum/parsers/miserables.rb +54 -0
  45. data/lib/rgraphum/parsers.rb +32 -0
  46. data/lib/rgraphum/path.rb +37 -0
  47. data/lib/rgraphum/query.rb +130 -0
  48. data/lib/rgraphum/rgraphum_array.rb +159 -0
  49. data/lib/rgraphum/rgraphum_array_dividers.rb +43 -0
  50. data/lib/rgraphum/rgraphum_random.rb +5 -0
  51. data/lib/rgraphum/simulator/ba_model.rb +140 -0
  52. data/lib/rgraphum/simulator/sir_model.rb +178 -0
  53. data/lib/rgraphum/simulator/sis_model.rb +158 -0
  54. data/lib/rgraphum/simulator.rb +29 -0
  55. data/lib/rgraphum/statistic/power_law.rb +9 -0
  56. data/lib/rgraphum/t.rb +12 -0
  57. data/lib/rgraphum/tf_idf.rb +27 -0
  58. data/lib/rgraphum/version.rb +3 -0
  59. data/lib/rgraphum/vertex.rb +354 -0
  60. data/lib/rgraphum/vertices.rb +97 -0
  61. data/lib/rgraphum.rb +38 -0
  62. data/performance/add-vertices-edges.rb +20 -0
  63. data/performance/add-vertices.rb +12 -0
  64. data/performance/build-graph.rb +19 -0
  65. data/performance/delete-graph.rb +24 -0
  66. data/performance/delete-vertices.rb +25 -0
  67. data/performance/refer-graph.rb +23 -0
  68. data/rgraphum.gemspec +30 -0
  69. data/test/lib/rgraphum/analyzer/linear_regression_test.rb +20 -0
  70. data/test/lib/rgraphum/analyzer/meme_tracker_test.rb +383 -0
  71. data/test/lib/rgraphum/analyzer/twitter/rt_at_mark_test.rb +120 -0
  72. data/test/lib/rgraphum/array_test.rb +95 -0
  73. data/test/lib/rgraphum/bubble_test.rb +7 -0
  74. data/test/lib/rgraphum/communities_test.rb +53 -0
  75. data/test/lib/rgraphum/cosine_similarity_test.rb +18 -0
  76. data/test/lib/rgraphum/edge_test.rb +89 -0
  77. data/test/lib/rgraphum/edges_test.rb +178 -0
  78. data/test/lib/rgraphum/graph_builder_test.rb +64 -0
  79. data/test/lib/rgraphum/graph_dup_test.rb +199 -0
  80. data/test/lib/rgraphum/graph_plus_test.rb +80 -0
  81. data/test/lib/rgraphum/graph_test.rb +512 -0
  82. data/test/lib/rgraphum/gremlin_test.rb +145 -0
  83. data/test/lib/rgraphum/importers/idg_json_edges.json +20 -0
  84. data/test/lib/rgraphum/importers/idg_json_test.rb +207 -0
  85. data/test/lib/rgraphum/importers/idg_json_vertices.json +46 -0
  86. data/test/lib/rgraphum/math/average_distance_matrix_test.rb +142 -0
  87. data/test/lib/rgraphum/math/clustering_coefficient_test.rb +219 -0
  88. data/test/lib/rgraphum/math/community_test.rb +78 -0
  89. data/test/lib/rgraphum/math/degree_distribution_test.rb +40 -0
  90. data/test/lib/rgraphum/math/dijkstra_test.rb +146 -0
  91. data/test/lib/rgraphum/math/modularity_test.rb +154 -0
  92. data/test/lib/rgraphum/math/quick_average_distance_matrix_test.rb +84 -0
  93. data/test/lib/rgraphum/path_test.rb +44 -0
  94. data/test/lib/rgraphum/query/enumerable_test.rb +42 -0
  95. data/test/lib/rgraphum/query/where_operators_test.rb +75 -0
  96. data/test/lib/rgraphum/query/where_test.rb +59 -0
  97. data/test/lib/rgraphum/simulator/ba_model_test.rb +75 -0
  98. data/test/lib/rgraphum/simulator/sir_model_test.rb +513 -0
  99. data/test/lib/rgraphum/simulator/sis_model_test.rb +478 -0
  100. data/test/lib/rgraphum/simulator_test.rb +22 -0
  101. data/test/lib/rgraphum/tf_idf_test.rb +30 -0
  102. data/test/lib/rgraphum/vertex_test.rb +50 -0
  103. data/test/lib/rgraphum/vertices_test.rb +180 -0
  104. data/test/test_helper.rb +98 -0
  105. data/tmp/.gitkeep +0 -0
  106. metadata +254 -0
@@ -0,0 +1,53 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Rgraphum::Graph::Math::ClusteringCoefficient
4
+ def self.included(base)
5
+ base.extend ClassMethods
6
+ base::RGRAPHUM::Vertex.send :include, VertexMethods
7
+ end
8
+
9
+ # Global clustering coefficient
10
+ #
11
+ # Returns clustering coefficient in Rational
12
+ #
13
+ def clustering_coefficient
14
+ n = vertices.size
15
+ # vertices.inject(0) { |cc, vertex|
16
+ # cc + (vertex.clustering_coefficient / n)
17
+ # }
18
+ sum_of_local_clustering_coefficient = vertices.inject(0) { |cc, vertex|
19
+ cc + (vertex.clustering_coefficient)
20
+ }
21
+ sum_of_local_clustering_coefficient / n
22
+ end
23
+
24
+ module ClassMethods
25
+ end
26
+
27
+ module VertexMethods
28
+ # Local clustering coefficient
29
+ #
30
+ # <pre>
31
+ # open triplet closed triplet
32
+ # V1 V2 V1 - V2
33
+ # \ / \ /
34
+ # V3 V3
35
+ # </pre>
36
+ #
37
+ def clustering_coefficient
38
+ ajacency_vertices = both
39
+ return Rational(0) if ajacency_vertices.size < 2
40
+ num_open_triplets, num_close_triplets = 0, 0
41
+ ajacency_vertices.combination(2) do |(v1, v2)|
42
+ va, vb = v1, v2
43
+ va, vb = v2, v1 if v1.edges.size > v2.edges.size
44
+ if va.edges.any? { |e| e.bothV.include?(vb) }
45
+ num_close_triplets += 1
46
+ else
47
+ num_open_triplets += 1
48
+ end
49
+ end
50
+ Rational(num_close_triplets, num_open_triplets + num_close_triplets)
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,141 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Rgraphum::Graph::Math
4
+ end
5
+
6
+ # Community Detection by Girvan?Newman algorithm
7
+ # 1st Set all vertex on each uniq communiy
8
+ # 2nd find edges within communities and make communities pair
9
+ # 3rd calc delta_q if marge communities pair
10
+ # 4th max delta_q communities pair is marged
11
+ # 5th update delta_q and do 4th
12
+ # 6th if dalta_q <= limit, stop community detection
13
+ class Rgraphum::Graph::Math::CommunityDetection
14
+
15
+ def initialize(graph,limit = 0)
16
+ @graph = graph
17
+ @m = graph.m_with_weight
18
+ @limit = 0
19
+
20
+ @modularity = 0
21
+ @id_community_hash = {}
22
+ initial_modularity_and_communities
23
+ @delta_q_hash = {}
24
+ initial_delta_q_hash
25
+
26
+ end
27
+
28
+ # modularity
29
+ # main loop of community_detection and cale modularity with delta_q( = delta_modularity )
30
+ #
31
+ def modularity
32
+
33
+ loop do
34
+ (community_id_a, community_id_b), delta_q = @delta_q_hash.max { |a, b| a[1] <=> b[1] }
35
+
36
+ break unless community_id_a && community_id_b && delta_q
37
+ break if delta_q <= @limit
38
+
39
+ @modularity += delta_q / (2.0 * @m ** 2)
40
+
41
+ community_a = @id_community_hash[community_id_a]
42
+ community_b = @id_community_hash[community_id_b]
43
+
44
+ community_a.merge(community_b)
45
+ @delta_q_hash = update_delta_q_hash(community_id_a, community_id_b, @delta_q_hash)
46
+ end
47
+
48
+ @modularity
49
+ end
50
+
51
+
52
+ def initial_modularity_and_communities
53
+
54
+ @graph.vertices.each_with_index do |vertex, i|
55
+ vertex.community_id = i
56
+ unless vertex.edges == []
57
+ community = Rgraphum::Community.new(id: vertex.community_id, graph: self, vertices: [vertex])
58
+ @id_community_hash[i] = community
59
+ @modularity -= vertex.degree_weight.to_f ** 2 / (2.0 * @m ) ** 2
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ # delta_q_hash: Hash
66
+ # key: [community_a.id, community_b.id] # Array of Integer
67
+ # value: delta_q_seed # Float
68
+ def initial_delta_q_hash( limit=0 )
69
+ @graph.edges.each do |edge|
70
+ s_c_id = edge[:source].community_id
71
+ t_c_id = edge[:target].community_id
72
+
73
+ # don't use loop
74
+ next if s_c_id == t_c_id
75
+
76
+ key = [ s_c_id, t_c_id ].sort!
77
+
78
+ delta_q_seed = delta_q_seed( @id_community_hash[ key[0] ] , @id_community_hash[ key[1] ] )
79
+ next if delta_q_seed <= limit
80
+ @delta_q_hash[key] = delta_q_seed
81
+ end
82
+ end
83
+
84
+
85
+ # ΔQ = Qa - Qb
86
+ def delta_q(community_a, community_b)
87
+ seed = delta_q_seed(community_a, community_b)
88
+ seed / (2.0 * @m ** 2)
89
+ end
90
+
91
+ private
92
+
93
+ def update_delta_q_hash(community_id_a, community_id_b, delta_q_hash)
94
+ a_id = community_id_a
95
+ b_id = community_id_b
96
+
97
+ new_keys = []
98
+ used_keys = []
99
+
100
+ # b_id -> a_id
101
+ @delta_q_hash.delete_if do |key,value|
102
+ next true if key == [a_id,b_id]
103
+ next false unless index = key.index(b_id)
104
+
105
+ key_dup = key.dup
106
+ key_dup[index] = a_id
107
+
108
+ key_dup.sort!
109
+ new_keys << key_dup
110
+ end
111
+
112
+ new_keys.each do |key|
113
+ @delta_q_hash[key] = 0.0
114
+ end
115
+
116
+ # update delta_q_value
117
+ community_a = @id_community_hash[a_id]
118
+ @delta_q_hash.each do |key, value|
119
+ if a_key_index = key.index(a_id)
120
+ o_key_index = a_key_index - 1
121
+ o_id = key[o_key_index]
122
+ other_community = @id_community_hash[o_id]
123
+
124
+ delta_q_seed = delta_q_seed(community_a, other_community)
125
+ next if delta_q_seed <= @limit
126
+ @delta_q_hash[key] = delta_q_seed
127
+ end
128
+ end
129
+
130
+ @delta_q_hash
131
+ end
132
+
133
+ def delta_q_seed(community_a, community_b)
134
+ tot_i = community_a.degree_weight
135
+ tot_j = community_b.degree_weight
136
+
137
+ ki_in = community_a.edges_from(community_b).inject(0) { |sum, edge| sum + edge.weight }
138
+
139
+ 2.0 * @m * ki_in - tot_i * tot_j
140
+ end
141
+ end
@@ -0,0 +1,50 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Rgraphum::Graph::Math
4
+
5
+ class DegreeDistribution
6
+ attr_reader :degree_distribution
7
+
8
+ def initialize(graph)
9
+ degree_distribution = {}
10
+
11
+ graph.vertices.each do |vertex|
12
+ degree_distribution[vertex.degree] ||= 0
13
+ degree_distribution[vertex.degree] += 1
14
+ end
15
+
16
+ @degree_distribution = {}
17
+ degree_distribution.each do |key, value|
18
+ @degree_distribution[key] = value.to_f / graph.vertices.size
19
+ end
20
+
21
+ self
22
+ end
23
+
24
+ def exponent
25
+ loged_degree_distribution = to_log
26
+ ral = Rgraphum::Analyzer::LinearRegression.new
27
+ ral.analyze(loged_degree_distribution.keys, loged_degree_distribution.values).first
28
+ end
29
+
30
+ def to_log
31
+ output ={}
32
+ @degree_distribution.each do |key,value|
33
+ output[Math.log(key, 10)] = Math.log(value, 10)
34
+ end
35
+ output
36
+ end
37
+ end
38
+
39
+ def degree_distribution(force=false)
40
+ @degree_distribution = nil if force
41
+ @degree_distribution ||= DegreeDistribution.new(self)
42
+ @degree_distribution.degree_distribution
43
+ end
44
+
45
+ def degree_distribution_exponent(force=false)
46
+ @degree_distribution = nil if force
47
+ @degree_distribution ||= DegreeDistribution.new(self)
48
+ @degree_distribution.exponent
49
+ end
50
+ end
@@ -0,0 +1,331 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # A --(1)-- B --(4)-- G
4
+ # | \ | /
5
+ #(2) (4) (2) (1)
6
+ # | \ | /
7
+ # C --(3)-- D
8
+ #
9
+ # A -> B -> D -> G
10
+ #
11
+ #
12
+ # \ A B C D G
13
+ # A - 1 2 4 -
14
+ # B 1 - - 2 4
15
+ # C 2 - - 3 -
16
+ # D 4 2 3 - 1
17
+ # G - 4 - 1 -
18
+ #
19
+ # \ A B C D G
20
+ # A - 1 2 4 -
21
+ # B - - - 2 4
22
+ # C - - - 3 -
23
+ # D - - - - 1
24
+ # G - - - - -
25
+ #
26
+ # \ A B C D G
27
+ # A - 1 2 4 -
28
+ # B - - - 2 4
29
+ # C - - - 3 -
30
+ # D - - - - 1
31
+ # G - - - - -
32
+ #
33
+ # A-B 1
34
+ # A-C 2
35
+ # A-D 4
36
+ #
37
+ # A-B-D 1+2=3
38
+ # A-B-G 1+4=5
39
+ # A-C 1
40
+ # A-D 4
41
+ #
42
+ # A-B-D 1+2=3
43
+ # A-B-G 1+4=5
44
+ # A-C-D 1+3=4
45
+ # A-D 4
46
+ #
47
+ # A-B-D 1+2=3
48
+ # A-B-G 1+4=5
49
+ # A-C-D 1+3=4 x
50
+ # A-D 4
51
+ #
52
+ # A-B-D-G 1+2+1=4
53
+ # A-B-G 1+4 =5 x
54
+ # A-C-D 1+3 =4 x
55
+ # A-D 4 x
56
+ #
57
+ module Rgraphum::Graph::Math::Dijkstra
58
+ def self.included(base)
59
+ base.extend ClassMethods
60
+ end
61
+
62
+ # Find shortest route from start to end
63
+ #
64
+ # Returns array of vertices
65
+ #
66
+ def dijkstra(start_vertex, end_vertex)
67
+ self.class.dijkstra(self, start_vertex, end_vertex)
68
+ end
69
+
70
+ def adjacency_matrix
71
+ self.class.adjacency_matrix(self)
72
+ end
73
+
74
+ def average_distance
75
+ self.class.average_distance(self)
76
+ end
77
+
78
+ def quick_average_distance
79
+ self.class.quick_average_distance(self)
80
+ end
81
+
82
+ def minimum_distance_matrix
83
+ self.class.minimum_distance_matrix(self)
84
+ end
85
+
86
+ module ClassMethods
87
+ # class Route
88
+ # attr_reader :id
89
+ # attr_accessor :vertices, :total_weight, :ended
90
+ #
91
+ # def initialize(vertex, options={})
92
+ # weight = options[:weight] || 1
93
+ # end_vertex = options[:end_vertex]
94
+ # end_id = end_vertex ? end_vertex.id : options[:end_id]
95
+ # if options.key?(:start_vertex)
96
+ # start_vertex = options[:start_vertex]
97
+ # @id = vertex.id
98
+ # @vertices = [start_vertex, vertex]
99
+ # @total_weight = weight
100
+ # @ended = (id == end_id)
101
+ # elsif options.key?(:route)
102
+ # route = options[:route]
103
+ # @id = vertex.id
104
+ # @vertices = route[:vertices] + [vertex]
105
+ # @total_weight = route[:total_weight] + weight
106
+ # @ended = (id == end_id)
107
+ # else
108
+ # raise ArgumentError
109
+ # end
110
+ # end
111
+ # end
112
+
113
+ # Find shortest route from start to end
114
+ #
115
+ # Returns array of vertices
116
+ #
117
+ def dijkstra(graph, start_vertex, end_vertex)
118
+ details = dijkstra_details(graph, start_vertex, end_vertex)
119
+ routes = details[:routes]
120
+
121
+ return [] if routes.nil? || routes.empty?
122
+ routes[0][:vertices]
123
+ end
124
+
125
+ # Find shortest routes from start to end
126
+ #
127
+ # Returns routes
128
+ #
129
+ def dijkstra_details(graph, start_vertex, end_vertex)
130
+ return {} if start_vertex.id == end_vertex.id
131
+
132
+ end_id = end_vertex.id
133
+ size = graph.vertices.size
134
+
135
+ shortest_map = Array.new(size, Float::INFINITY)
136
+ adjacency_matrix = adjacency_matrix(graph)
137
+
138
+ routes = []
139
+
140
+ start_index = graph.vertices.index(start_vertex)
141
+ weights = adjacency_matrix[start_index]
142
+ weights.each_with_index do |weight, i|
143
+ next unless weight
144
+ shortest_map[i] = weight
145
+
146
+ vertex = graph.vertices[i]
147
+ routes << {
148
+ id: vertex.id,
149
+ index: i,
150
+ vertices: [start_vertex, vertex],
151
+ weights: [weight],
152
+ total_weight: weight,
153
+ ended: vertex.id == end_id,
154
+ }
155
+ end
156
+
157
+ loop do
158
+ shortest_route = routes.min_by { |route|
159
+ route[:ended] ? Float::INFINITY : route[:total_weight]
160
+ }
161
+ break if !shortest_route || shortest_route[:ended]
162
+
163
+ routes.delete shortest_route
164
+ weights = adjacency_matrix[shortest_route[:index]]
165
+ weights.each_with_index do |weight, i|
166
+ next unless weight
167
+ vertex = graph.vertices[i]
168
+ next if shortest_route[:vertices].include?(vertex)
169
+
170
+ total_weight = shortest_route[:total_weight] + weight
171
+ next if shortest_map[i] < total_weight
172
+ shortest_map[i] = total_weight
173
+
174
+ routes << {
175
+ id: vertex.id,
176
+ index: i,
177
+ vertices: shortest_route[:vertices] + [vertex],
178
+ weights: shortest_route[:weights] + [weight],
179
+ total_weight: shortest_route[:total_weight] + weight,
180
+ ended: vertex.id == end_id,
181
+ }
182
+ end
183
+
184
+ remove_long_routes routes
185
+ end
186
+
187
+ {
188
+ graph: graph,
189
+ start_vertex: start_vertex,
190
+ end_vertex: end_vertex,
191
+ routes: routes,
192
+ shortest_map: shortest_map,
193
+ adjacency_matrix: adjacency_matrix,
194
+ }
195
+ end
196
+
197
+ # 隣接行列 Adjacency matrix
198
+ def adjacency_matrix(graph)
199
+ ids = graph.vertices.map(&:id)
200
+ id_index_map = Hash[*ids.map.with_index { |id, i| [id, i] }.flatten]
201
+ size = graph.vertices.size
202
+ adjacency_matrix = (0...size).map { Array.new(size) }
203
+
204
+ graph.edges.each do |e|
205
+ i = id_index_map[e.source.id]
206
+ j = id_index_map[e.target.id]
207
+ adjacency_matrix[i][j] = e.weight
208
+ adjacency_matrix[j][i] = e.weight # FIXME
209
+ end
210
+
211
+ adjacency_matrix
212
+ end
213
+
214
+ def average_distance_with_minimum_distance_matrix(graph, &block)
215
+ minimum_distance_matrix = yield
216
+ n = minimum_distance_matrix.size
217
+ total_minimum_distane = 0
218
+ (0...n).each do |i|
219
+ ((i+1)...n).each do |j|
220
+ total_minimum_distane += minimum_distance_matrix[i][j]
221
+ end
222
+ end
223
+ Rational(total_minimum_distane, Rational(n * (n-1), 2))
224
+ end
225
+
226
+ def average_distance(graph)
227
+ average_distance_with_minimum_distance_matrix(graph) {
228
+ minimum_distance_matrix(graph)
229
+ }
230
+ end
231
+
232
+ def quick_average_distance(graph)
233
+ average_distance_with_minimum_distance_matrix(graph) {
234
+ quick_minimum_distance_matrix(graph)
235
+ }
236
+ end
237
+
238
+ def minimum_distance_matrix(graph)
239
+ size = graph.vertices.size
240
+ distance_matrix = (0...size).map { Array.new(size) }
241
+
242
+ (0...size).each do |i|
243
+ (i...size).each do |j|
244
+ if i == j
245
+ distance = 0
246
+ else
247
+ v1, v2 = graph.vertices[i], graph.vertices[j]
248
+ details = dijkstra_details(graph, v1, v2)
249
+ weights = details[:routes][0][:weights] rescue []
250
+ if weights.empty?
251
+ distance = nil
252
+ else
253
+ distance = weights.inject(0, &:+)
254
+ end
255
+ end
256
+ distance_matrix[i][j] = distance
257
+ end
258
+ end
259
+
260
+ (0...(size-1)).each do |i|
261
+ ((i+1)...size).each do |j|
262
+ distance_matrix[j][i] = distance_matrix[i][j]
263
+ end
264
+ end
265
+
266
+ distance_matrix
267
+ end
268
+
269
+ def quick_minimum_distance_matrix(graph)
270
+ size = graph.vertices.size
271
+ distance_matrix = (0...size).map { Array.new(size) }
272
+
273
+ remaining_paths = {}
274
+ (0...(size-1)).each do |i|
275
+ ((i+1)...size).each do |j|
276
+ remaining_paths[[i, j]] = true
277
+ end
278
+ end
279
+
280
+ until remaining_paths.empty?
281
+ (i, j), _ = remaining_paths.shift
282
+ v1, v2 = graph.vertices[i], graph.vertices[j]
283
+
284
+ details = dijkstra_details(graph, v1, v2)
285
+ weights = details[:routes][0][:weights] rescue []
286
+ if weights.empty?
287
+ distance_matrix[i][j] = nil
288
+ else
289
+ route_vertices = details[:routes][0][:vertices]
290
+ route_vertices_size = route_vertices.size
291
+
292
+ (0...(route_vertices_size-1)).each do |k|
293
+ ((k+1)...route_vertices_size).each do |l|
294
+ m = graph.vertices.index(route_vertices[k])
295
+ n = graph.vertices.index(route_vertices[l])
296
+ m, n = n, m if m > n
297
+ unless distance_matrix[m][n]
298
+ distance_matrix[m][n] = weights[k..l].inject(0, &:+)
299
+ remaining_paths.delete [m, n]
300
+ end
301
+ end
302
+ end
303
+ end
304
+ end
305
+
306
+ (0...size).each do |i|
307
+ distance_matrix[i][i] = 0
308
+ end
309
+ (0...(size-1)).each do |i|
310
+ ((i+1)...size).each do |j|
311
+ distance_matrix[j][i] = distance_matrix[i][j]
312
+ end
313
+ end
314
+
315
+ distance_matrix
316
+ end
317
+
318
+ def remove_long_routes(routes)
319
+ ended_routes = routes.select { |route| route[:ended] }
320
+ shortest_ended_route = ended_routes.min_by { |route| route[:total_weight] }
321
+
322
+ if shortest_ended_route
323
+ routes.reject! do |route|
324
+ shortest_ended_route[:total_weight] < route[:total_weight]
325
+ end
326
+ end
327
+ end
328
+ end
329
+
330
+ private
331
+ end
@@ -0,0 +1,45 @@
1
+ # -*- coding: utf-8 -*-
2
+ class Rgraphum::Graph
3
+ end
4
+
5
+ module Rgraphum::Graph::Math
6
+ require_relative 'math/dijkstra'
7
+ require_relative 'math/clustering_coefficient'
8
+ require_relative 'math/degree_distribution'
9
+ require_relative 'math/community_detection'
10
+
11
+ def self.included(base)
12
+ # base.extend ClassMethods
13
+ base.send :include, Rgraphum::Graph::Math::Dijkstra
14
+ base.send :include, Rgraphum::Graph::Math::ClusteringCoefficient
15
+ end
16
+
17
+ def modularity
18
+ CommunityDetection.new(self).modularity
19
+ end
20
+
21
+ def communities
22
+ existing_community_ids = {}
23
+ communities = []
24
+ @vertices.each do |vertex|
25
+ next if existing_community_ids.key?(vertex.community_id)
26
+ community = community_by_id(vertex.community_id)
27
+ communities << community
28
+ existing_community_ids[community.id] = true
29
+ end
30
+ Rgraphum::Communities(communities)
31
+ end
32
+
33
+ def power_low_rand(max,min,exponent)
34
+ ( (max^exponent-min^exponent)*rand() + min^exponent )^( 1.0/exponent )
35
+ end
36
+
37
+ private
38
+
39
+ def community_by_id(community_id)
40
+ community_id = community_id.id if community_id.is_a?(Rgraphum::Community)
41
+ vertices = @vertices.find_all { |vertex| vertex.community_id == community_id }
42
+ Rgraphum::Community.new(id: community_id, graph: self, vertices: vertices)
43
+ end
44
+
45
+ end