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