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,54 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require 'json'
4
+
5
+ module Rgraphum::Parsers
6
+ class MiserablesParser
7
+ class << self
8
+ def builder(graph)
9
+ stream = "var miserables = { vertices: ["
10
+
11
+ graph.vertices.each_with_index do |vertex, n|
12
+ vertex.class_eval { attr_accessor :no } # FIXME
13
+ vertex.no = n
14
+ # stream += "\n{vertexName: \"#{vertex.label}\", group: #{vertex[:community_id]}},"
15
+ stream += "\n" + { vertexName: vertex.label, group: vertex.community_id }.to_json + ","
16
+ end
17
+ stream.chop!
18
+ stream += "],\n"
19
+
20
+ stream += "links: ["
21
+ graph.edges.each do |edge|
22
+ stream += "\n{source: #{edge.source.no},"
23
+ stream += " target: #{edge.target.no},"
24
+ stream += " value: #{edge.weight}},"
25
+ end
26
+ stream.chop!
27
+ stream += "]\n"
28
+ stream += "};"
29
+
30
+ stream
31
+ end
32
+ end
33
+
34
+ # Options:
35
+ #
36
+ def initialize(options={})
37
+ default_options = {
38
+ }
39
+ @options = default_options.merge(options)
40
+ builder(@options[:graph]) if @options.key?(:graph)
41
+ end
42
+
43
+ def builder(graph)
44
+ @stream = self.class.builder(graph)
45
+ end
46
+
47
+ def to_s
48
+ unless @stream
49
+ raise ArgumentError, "Didn't build stream with builder(graph)"
50
+ end
51
+ @stream
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,32 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require_relative 'parsers/gephi'
4
+ require_relative 'parsers/miserables'
5
+ require_relative 'parsers/graphviz'
6
+ require_relative 'parsers/flare'
7
+
8
+ module Rgraphum::Parsers
9
+ # parsers
10
+ def to_gephi
11
+ self.real_aspect! if @aspect == "id"
12
+ gephi_xml = Rgraphum::Parsers::GephiParser.new(graph: self)
13
+ end
14
+
15
+ def to_miserables
16
+ self.real_aspect! if @aspect == "id"
17
+ stream = Rgraphum::Parsers::MiserablesParser.new(graph: self)
18
+ end
19
+
20
+ def to_graphviz( options={} )
21
+ self.real_aspect! if @aspect == "id"
22
+ default_options = { graph:self, layout: "dot" }
23
+ options = default_options.merge(options)
24
+ dot = Rgraphum::Parsers::GraphvizParser.new( options )
25
+ end
26
+
27
+ def to_flare
28
+ self.real_aspect! if @aspect == "id"
29
+ stream = Rgraphum::Parsers::MiserablesParser.new(graph: self)
30
+ end
31
+
32
+ end
@@ -0,0 +1,37 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Rgraphum::Path
4
+ attr_reader :end_vertex
5
+ attr_reader :vertices
6
+
7
+ # vertices: Array of Rgraphum::Vertex
8
+ #
9
+ def initialize(end_vertex=nil, vertices=[])
10
+ @end_vertex = end_vertex
11
+ @vertices = vertices
12
+ end
13
+
14
+ def include?(vertex)
15
+ vertices.include?(vertex)
16
+ end
17
+
18
+ def edges
19
+ # FIXME
20
+ last_vertex = vertices.first
21
+ graph = last_vertex.graph
22
+ new_edges = []
23
+ vertices.each do |vertex|
24
+ if last_vertex != vertex
25
+ edge = graph.edges.where(source: last_vertex, target: vertex).first
26
+ edge ||= graph.edges.where(source: vertex, target: last_vertex).first
27
+ new_edges << edge
28
+ end
29
+ last_vertex = vertex
30
+ end
31
+ new_edges
32
+ end
33
+
34
+ def total_weight
35
+ edges.inject(0) { |sum, edge| sum + edge.weight }
36
+ end
37
+ end
@@ -0,0 +1,130 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ class Rgraphum::Query
4
+ include Enumerable
5
+
6
+ def initialize(array, *conditions)
7
+ @array = array
8
+ @conditions = []
9
+ @id_conditions = nil
10
+ where(*conditions)
11
+ end
12
+
13
+ def each(&block)
14
+ if block_given?
15
+ all.each do |item|
16
+ yield item
17
+ end
18
+ else
19
+ to_enum
20
+ end
21
+ end
22
+
23
+ def empty?
24
+ all.empty?
25
+ end
26
+
27
+ # where(id: 3).first
28
+ # where(label: "abc").all
29
+ # where(id: 1, label: "abc").all
30
+ # where(:label, :eq, "abc").all
31
+ # where(:label, :ne, "abc").all
32
+ def where(*conditions)
33
+ if conditions.size == 1 && conditions[0].is_a?(Hash)
34
+ conditions = conditions[0]
35
+ end
36
+ return self if conditions.empty?
37
+
38
+ case conditions
39
+ when Hash
40
+ conditions.each do |fieldname, rvalue|
41
+ condition = [fieldname, :eq, rvalue]
42
+ @conditions << condition
43
+ if fieldname == :id
44
+ @id_conditions ||= []
45
+ @id_conditions << condition
46
+ end
47
+ end
48
+ when Array
49
+ fieldname, operator, rvalue = conditions
50
+ condition = [fieldname, operator, rvalue]
51
+ @conditions << condition
52
+ if fieldname == :id && (operator == :eq || operator == :==)
53
+ @id_conditions ||= []
54
+ @id_conditions << condition
55
+ end
56
+ else
57
+ raise NotImplementedError
58
+ end
59
+
60
+ self
61
+ end
62
+
63
+ def all
64
+ if @id_conditions && @array.respond_to?(:find_by_id)
65
+ item = @array.find_by_id(@id_conditions.first[2])
66
+ if try_conditions(item)
67
+ [item]
68
+ else
69
+ []
70
+ end
71
+ else
72
+ @array.class.new( @array.select { |item| try_conditions(item) } )
73
+ end
74
+ end
75
+ alias :to_a :all
76
+
77
+ def first
78
+ if @id_conditions && @array.respond_to?(:find_by_id)
79
+ item = @array.find_by_id(@id_conditions.first[2])
80
+ return item if item && try_conditions(item)
81
+ else
82
+ @array.each do |item|
83
+ return item if try_conditions(item)
84
+ end
85
+ end
86
+ nil
87
+ end
88
+
89
+ def last
90
+ if @id_conditions && @array.respond_to?(:find_by_id)
91
+ item = @array.find_by_id(@id_conditions.first[2])
92
+ return item if item && try_conditions(item)
93
+ else
94
+ @array.reverse_each do |item|
95
+ return item if try_conditions(item)
96
+ end
97
+ end
98
+ nil
99
+ end
100
+
101
+ def method_missing(method_name, *args)
102
+ if @array.first.respond_to?(method_name)
103
+ all.map { |item| item.send(method_name) }
104
+ else
105
+ super
106
+ end
107
+ end
108
+
109
+ private
110
+
111
+ def try_conditions(item)
112
+ @conditions.each do |(fieldname, operator, rvalue)|
113
+ lvalue = item.send(fieldname)
114
+ case operator
115
+ when :eq, :==; return false unless lvalue == rvalue
116
+ when :ne, :!=; return false unless lvalue != rvalue
117
+ when :gt, :>; return false unless lvalue > rvalue
118
+ when :gte, :>=; return false unless lvalue >= rvalue
119
+ when :lt, :<; return false unless lvalue < rvalue
120
+ when :lte, :<=; return false unless lvalue <= rvalue
121
+ when :match, :=~; return false unless lvalue =~ rvalue
122
+ when :not_match, :!~; return false unless lvalue !~ rvalue
123
+ else
124
+ raise ArgumentError, "Unknown operator #{operator}"
125
+ end
126
+ end
127
+ true
128
+ end
129
+
130
+ end
@@ -0,0 +1,159 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ require_relative 'query'
4
+
5
+ class Rgraphum::RgraphumArray < Array
6
+ attr_accessor :graph
7
+
8
+ # def ids
9
+ # map { |obj| obj.id }
10
+ # end
11
+
12
+ # FIXME use initialize_copy instead
13
+ def dup
14
+ array = self.class.new
15
+ each do |item|
16
+ array << item.dup
17
+ end
18
+ array
19
+ end
20
+
21
+ def self.reset_id
22
+ remove_instance_variable :@new_id
23
+ end
24
+
25
+ # FIXME maybe better id to start from 1
26
+ # def self.new_id
27
+ # @new_id ||= -1
28
+ # @new_id += 1
29
+ # end
30
+
31
+ def new_id(id=nil)
32
+ # self.class.new_id
33
+ @new_id ||= -1
34
+ if id
35
+ @new_id = id if @new_id < id
36
+ id
37
+ else
38
+ @new_id += 1
39
+ end
40
+ end
41
+
42
+ def substitute(array, &block)
43
+ return unless array.is_a?(Array)
44
+ new_array = self.class.new
45
+ new_array.graph = @graph
46
+ array.each do |item|
47
+ if block_given?
48
+ new_array << (yield item)
49
+ else
50
+ new_array << item
51
+ end
52
+ end
53
+ new_array
54
+ end
55
+
56
+ alias :original_delete_if :delete_if
57
+ alias :original_reject! :reject!
58
+ def delete_if
59
+ if block_given?
60
+ i = 0
61
+ size = self.size
62
+ while i < size
63
+ item = self[i]
64
+ if yield(item)
65
+ delete(item)
66
+ size -= 1
67
+ else
68
+ i += 1
69
+ end
70
+ end
71
+ self
72
+ else
73
+ to_enum
74
+ end
75
+ end
76
+ alias :reject! :delete_if
77
+
78
+ alias :original_reject :reject
79
+ def reject(&block)
80
+ dup.reject! &block
81
+ end
82
+
83
+ def where(*conditions)
84
+ Rgraphum::Query.new(self, *conditions)
85
+ end
86
+
87
+ # gremlin methods
88
+
89
+ # has
90
+ # Allows an element if it has a particular property. Utilizes several options for comparisons through T:
91
+ # T.gt - greater than
92
+ # T.gte - greater than or equal to
93
+ # T.eq - equal to
94
+ # T.neq - not equal to
95
+ # T.lte - less than or equal to
96
+ # T.lt - less than
97
+ # It is worth noting that the syntax of has is similar to g.V("name", "marko"), which has the difference of being a key index lookup and as such will perform faster. In contrast, this line, g.V.has("name", "marko"), will iterate over all vertices checking the name property of each vertex for a match and will be significantly slower than the key index approach.
98
+ # gremlin> g.V.has("name", "marko").name
99
+ # ==>marko
100
+ # gremlin> g.v(1).outE.has("weight", T.gte, 0.5f).weight
101
+ # ==>0.5
102
+ # ==>1.0
103
+ # gremlin> g.V.has("age", null).name
104
+ # ==>lop
105
+ # ==>ripple
106
+ def has(*conditions)
107
+ if conditions.size == 1
108
+ self.class.new( where( conditions[0], :!=, nil ) )
109
+ elsif conditions.size == 2
110
+ self.class.new( where( { conditions[0] => conditions[1] } ) )
111
+ elsif conditions.size == 3
112
+ self.class.new( where( *conditions ) )
113
+ end
114
+ end
115
+
116
+ # hasNot
117
+ # Allows an element if it does not have a particular property. Utilizes several options for comparisons on through T:
118
+ # T.gt - greater than
119
+ # T.gte - greater than or equal to
120
+ # T.eq - equal to
121
+ # T.neq - not equal to
122
+ # T.lte - less than or equal to
123
+ # T.lt - less than
124
+ # gremlin> g.v(1).outE.hasNot("weight", T.eq, 0.5f).weight
125
+ # ==>1.0
126
+ # ==>0.4
127
+ # gremlin> g.V.hasNot("age", null).name
128
+ # ==>vadas
129
+ # ==>marko
130
+ # ==>peter
131
+ # ==>josh
132
+ def hasNot(*conditions)
133
+ nor_hash = {
134
+ :== => :!=,
135
+ :!= => :==,
136
+ :< => :>=,
137
+ :<= => :> ,
138
+ :>= => :<,
139
+ :> => :<=,
140
+ }
141
+
142
+ if conditions.size == 1
143
+ self.class.new( where( conditions[0], :==, nil ) )
144
+ elsif conditions.size == 2
145
+ where( conditions[0], :!=, conditions[1] )
146
+ elsif conditions.size == 3
147
+ where( conditions[0], nor_hash[conditions[1]], conditions[2] )
148
+ end
149
+ end
150
+
151
+ def method_missing(name, *args)
152
+ if first.class.has_field?(name)
153
+ map{|item| item.send(name)}
154
+ else
155
+ super(name,*args)
156
+ end
157
+ end
158
+
159
+ end
@@ -0,0 +1,43 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ module Rgraphum::RgraphumArrayDividers
4
+ def divide_by_time(interval=20)
5
+ # interval is min
6
+
7
+ base_sec = interval * 60
8
+
9
+ each do |item|
10
+ if item.start
11
+ item.start = time_rounddown(item.start, base_sec)
12
+
13
+ if item.end
14
+ item.end = time_roundup(item.end, base_sec)
15
+ else
16
+ item.end = time_roundup(item.start, base_sec)
17
+ end
18
+
19
+ if item.end > (item.start + base_sec)
20
+ (item.start.to_i + base_sec).step(item.end.to_i, base_sec) do |t|
21
+ new_item = item.dup
22
+ new_item.id = nil
23
+ new_item.start = Time.at(t)
24
+ new_item.end = Time.at(t + base_sec - 1)
25
+
26
+ self << new_item
27
+ end
28
+ item.end = Time.at(item.start.to_i + base_sec - 1)
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ private
35
+
36
+ def time_rounddown(time, sec)
37
+ Time.at((time.to_i / sec) * sec)
38
+ end
39
+
40
+ def time_roundup(time, sec)
41
+ Time.at((time.to_i / sec) * sec + sec - 1)
42
+ end
43
+ end
@@ -0,0 +1,5 @@
1
+ module Rgraphum::RgraphumRandom
2
+ def power_low_rand(max,min,exponent)
3
+ ( (max**exponent-min**exponent)*rand() + min**exponent )**( 1.0/exponent )
4
+ end
5
+ end
@@ -0,0 +1,140 @@
1
+ # -*- coding: utf-8 -*-
2
+
3
+ # About BA Model
4
+ # The BA Model is a mathematical model of the network with "growth" and "preferential attachment".
5
+ # Growth means that the network is added to vertices with a fixed number of edges one at a time.
6
+ # Preferential attachment shows that the more connected a vertex is, the more likely to receive new edge.
7
+ # An importance of the model is to generate scale-free networks.
8
+ # The consruction of the model is as follows;
9
+ # 1st: Select vertices with the probability of each degree / graph's total degree,
10
+ # 2nd: Add every selected vertices to new edge.
11
+ # 3rd: Repeat the 1st step and the 2nd step until the number of vertices attain the target one.
12
+ class Rgraphum::Simulator::BAModel
13
+ def initialize(options={})
14
+ if options[:graph]
15
+ @graph = options[:graph].dup
16
+ else
17
+ @graph = Rgraphum::Graph.new
18
+ end
19
+ end
20
+
21
+ # Simurate BAmodel
22
+ # @param [Hash] options BAmodel's options
23
+ # @option options [Graph] :graph (graph) start(base) origin graph.
24
+ # default is a graph which used on newly constructing BAModel
25
+ # @option options [Integer] :round (10,000) simurate rounds, this means added vertex size
26
+ # @option options [Integer] :edge_size (1) edge size on once added a vertex
27
+ # @option options [Integer] :interval (1) plus time(min) on new vertex and its edges if vertex or edge has 'cteated_at' value.
28
+ # @option options [Float] :new_vertex_rate (1.0) Probability of adding new vertex.
29
+ # If you need to add no new vertex but add edge, use this rate(0.0 - 1.0).
30
+ # default is 1.0. it means always add new vertex
31
+ # @return [Graph] a graph after simurate, not same origin graph.
32
+ #
33
+ def simulate(options={})
34
+ default_options = {
35
+ graph: @graph,
36
+ round: 10_000,
37
+ edge_size: 1,
38
+ interval: 1,
39
+ new_vertex_rate: 1.0,
40
+ random_seed: 10,
41
+ }
42
+ options = default_options.merge(options)
43
+
44
+ srand options[:random_seed]
45
+ graph = options[:graph]
46
+
47
+ base_vertices_size = graph.vertices.size
48
+
49
+ while graph.vertices.size - base_vertices_size < options[:round]
50
+ t_v = target_vertex(graph, options[:new_vertex_rate])
51
+ options[:edge_size].times do
52
+ edge = graph.edges.build( { source: source_vertex(graph), target: t_v } )
53
+ end
54
+ end
55
+ graph
56
+ end
57
+
58
+ # selecting source vertex method
59
+ # Propability of BAModel's vertex selection divide
60
+ # into probability of edges selection and probalility of source or target selection on edge.
61
+ # And select source vertex
62
+ def source_vertex(graph=@graph)
63
+ return graph.vertices.build({label: new_dummy_label}) if graph.edges.size == 0
64
+
65
+ edge_index = rand( graph.edges.size )
66
+ if rand(2) == 0
67
+ source_vertex = graph.edges[edge_index][:source]
68
+ else
69
+ source_vertex = graph.edges[edge_index][:target]
70
+ end
71
+ end
72
+
73
+ # selecting target vertex method
74
+ # with new_vertex_rate, select new vertex or existing vertex.
75
+ # if selectiong new vertex, make new vertex and add it on graph
76
+ # @param [Graph] graph (@graph)
77
+ # @param [Float] new_vertex_rate (1.0)
78
+ # @return [Vertex]
79
+ def target_vertex(graph=@graph, new_vertex_rate=1.0)
80
+ vertices = graph.vertices
81
+ if new_vertex_rate < rand and vertices.size > 0
82
+ target_vertex = vertices[rand(vertices.size)]
83
+ else
84
+ graph.vertices.build(label: new_dummy_label)
85
+ end
86
+ end
87
+
88
+ # new dummy label method
89
+ def new_dummy_label
90
+ @dummy_label_index ||= 0
91
+ @dummy_labels ||= ("a".."aaaaaa").to_a
92
+ dummy_label = @dummy_labels[@dummy_label_index]
93
+ @dummy_label_index += 1
94
+ dummy_label
95
+ end
96
+
97
+ ######################################################################
98
+ # @private
99
+ def vertices_per_min(graph=@graph)
100
+ return nil if graph.vertices.empty?
101
+ first_vertex = graph.vertices.min_by { |vertex| vertex.start }
102
+ last_vertex = graph.vertices.max_by { |vertex| vertex.start }
103
+ graph.vertices.size / ((last_vertex.start - first_vertex.start) / 60.0)
104
+ end
105
+
106
+ def edges_per_min(graph=@graph)
107
+ return nil if graph.edges.empty?
108
+ first_vertex = graph.edges.min_by { |edge| edge.start }
109
+ last_vertex = graph.edges.max_by { |edge| edge.start }
110
+ graph.edges.size / ((last_vertex.start - first_vertex.start) / 60.0)
111
+ end
112
+
113
+ def edges_size_array_per_interval(graph=@graph, interval=1)
114
+ sorted_edges = graph.edges.sort{ |a, b| a.start <=> b.start}
115
+ step = interval * 60
116
+
117
+ start_time = sorted_edges[0].start.to_i / step * 60
118
+ end_time = sorted_edges[-1].start.to_i / step * 60 + 1
119
+
120
+ time_array = []
121
+ time = start_time + step
122
+ size = 0
123
+ starts = sorted_edges.map { |edge| edge.start.to_i }
124
+
125
+ time, time_array = next_time(starts, time, step, time_array, size)
126
+
127
+ time_array
128
+ end
129
+
130
+ def next_time(sources, time, step, time_array, size)
131
+ return [time, time_array + [size]] if sources.empty?
132
+ if sources[0] >= time
133
+ time_array << size
134
+ time, time_array = next_time(sources, time+step, step, time_array, 0)
135
+ else
136
+ sources.shift
137
+ time, time_array = next_time(sources, time, step, time_array, size + 1)
138
+ end
139
+ end
140
+ end