rgraphum 0.0.1.alpha

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.
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