silicium 0.0.14 → 0.0.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/.codeclimate.yml +4 -0
  3. data/.gitignore +13 -11
  4. data/.rakeTasks +8 -0
  5. data/.travis.yml +17 -3
  6. data/CODE_OF_CONDUCT.md +74 -74
  7. data/Gemfile +8 -4
  8. data/LICENSE.txt +21 -21
  9. data/Makefile +269 -0
  10. data/README.md +588 -44
  11. data/Rakefile +17 -10
  12. data/bin/console +14 -14
  13. data/bin/setup +8 -8
  14. data/docs/Object.html +117 -0
  15. data/docs/README_md.html +142 -0
  16. data/docs/Silicium/Combinatorics.html +270 -0
  17. data/docs/Silicium/Dice/Polyhedron.html +315 -0
  18. data/docs/Silicium/Dice/PolyhedronSet.html +321 -0
  19. data/docs/Silicium/Dice.html +99 -0
  20. data/docs/Silicium/Error.html +106 -0
  21. data/docs/Silicium/Geometry/Line2dCanon.html +243 -0
  22. data/docs/Silicium/Geometry/VariablesOrderException.html +106 -0
  23. data/docs/Silicium/Geometry.html +940 -0
  24. data/docs/Silicium/GraphVisualizer.html +226 -0
  25. data/docs/Silicium/Graphs/GraphError.html +106 -0
  26. data/docs/Silicium/Graphs/OrientedGraph.html +901 -0
  27. data/docs/Silicium/Graphs/UnorientedGraph.html +237 -0
  28. data/docs/Silicium/Graphs.html +374 -0
  29. data/docs/Silicium/IntegralDoesntExistError.html +106 -0
  30. data/docs/Silicium/NumericalIntegration.html +521 -0
  31. data/docs/Silicium/Optimization.html +629 -0
  32. data/docs/Silicium/Plotter/Image.html +297 -0
  33. data/docs/Silicium/Plotter.html +186 -0
  34. data/docs/Silicium.html +101 -0
  35. data/docs/created.rid +9 -0
  36. data/docs/css/fonts.css +167 -0
  37. data/docs/css/rdoc.css +619 -0
  38. data/docs/fonts/Lato-Light.ttf +0 -0
  39. data/docs/fonts/Lato-LightItalic.ttf +0 -0
  40. data/docs/fonts/Lato-Regular.ttf +0 -0
  41. data/docs/fonts/Lato-RegularItalic.ttf +0 -0
  42. data/docs/fonts/SourceCodePro-Bold.ttf +0 -0
  43. data/docs/fonts/SourceCodePro-Regular.ttf +0 -0
  44. data/docs/images/add.png +0 -0
  45. data/docs/images/arrow_up.png +0 -0
  46. data/docs/images/brick.png +0 -0
  47. data/docs/images/brick_link.png +0 -0
  48. data/docs/images/bug.png +0 -0
  49. data/docs/images/bullet_black.png +0 -0
  50. data/docs/images/bullet_toggle_minus.png +0 -0
  51. data/docs/images/bullet_toggle_plus.png +0 -0
  52. data/docs/images/date.png +0 -0
  53. data/docs/images/delete.png +0 -0
  54. data/docs/images/find.png +0 -0
  55. data/docs/images/loadingAnimation.gif +0 -0
  56. data/docs/images/macFFBgHack.png +0 -0
  57. data/docs/images/package.png +0 -0
  58. data/docs/images/page_green.png +0 -0
  59. data/docs/images/page_white_text.png +0 -0
  60. data/docs/images/page_white_width.png +0 -0
  61. data/docs/images/plugin.png +0 -0
  62. data/docs/images/ruby.png +0 -0
  63. data/docs/images/tag_blue.png +0 -0
  64. data/docs/images/tag_green.png +0 -0
  65. data/docs/images/transparent.png +0 -0
  66. data/docs/images/wrench.png +0 -0
  67. data/docs/images/wrench_orange.png +0 -0
  68. data/docs/images/zoom.png +0 -0
  69. data/docs/index.html +134 -0
  70. data/docs/js/darkfish.js +84 -0
  71. data/docs/js/navigation.js +105 -0
  72. data/docs/js/navigation.js.gz +0 -0
  73. data/docs/js/search.js +110 -0
  74. data/docs/js/search_index.js +1 -0
  75. data/docs/js/search_index.js.gz +0 -0
  76. data/docs/js/searcher.js +229 -0
  77. data/docs/js/searcher.js.gz +0 -0
  78. data/docs/table_of_contents.html +697 -0
  79. data/lib/algebra.rb +452 -0
  80. data/lib/algebra_diff.rb +258 -0
  81. data/lib/geometry/figure.rb +62 -0
  82. data/lib/geometry.rb +290 -0
  83. data/lib/geometry3d.rb +270 -0
  84. data/lib/graph/dfs.rb +41 -0
  85. data/lib/graph/kruskal.rb +36 -0
  86. data/lib/graph/scc.rb +97 -0
  87. data/lib/graph.rb +350 -0
  88. data/lib/graph_visualizer.rb +286 -0
  89. data/lib/ml_algorithms.rb +181 -0
  90. data/lib/numerical_integration.rb +184 -0
  91. data/lib/optimization.rb +208 -0
  92. data/lib/plotter.rb +258 -0
  93. data/lib/polynomial_division.rb +132 -0
  94. data/lib/polynomial_interpolation.rb +94 -0
  95. data/lib/regression.rb +120 -0
  96. data/lib/silicium/adding.rb +37 -0
  97. data/lib/silicium/conversions.rb +23 -0
  98. data/lib/silicium/multi.rb +82 -0
  99. data/lib/silicium/sparse.rb +76 -0
  100. data/lib/silicium/sugar.rb +37 -0
  101. data/lib/silicium/trans.rb +26 -0
  102. data/lib/silicium/version.rb +3 -3
  103. data/lib/silicium.rb +29 -6
  104. data/lib/theory_of_probability.rb +240 -0
  105. data/lib/topological_sort.rb +50 -0
  106. data/oriented_graph.png +0 -0
  107. data/plot.png +0 -0
  108. data/silicium.gemspec +4 -3
  109. metadata +122 -12
@@ -0,0 +1,286 @@
1
+ require 'chunky_png'
2
+ require 'ruby2d'
3
+ require 'ruby2d/window'
4
+ module Silicium
5
+ module GraphVisualizer
6
+ include Silicium::Graphs
7
+ include Ruby2D
8
+
9
+
10
+ ##
11
+ # Changes window size
12
+ def change_window_size(w, h)
13
+ (Window.get :window).set width: w, height: h
14
+ end
15
+
16
+ ##
17
+ # Changes width of edges
18
+ def change_edge_width(w)
19
+ @@line_width = w
20
+ end
21
+
22
+ ##
23
+ # Changes radius of vertices
24
+ def change_vertices_radius(r)
25
+ @@vert_radius = r
26
+ end
27
+
28
+ ##
29
+ # Changes labels size
30
+ def change_label_size(s)
31
+ @@label_size = s
32
+ end
33
+
34
+ ##
35
+ # Changes labels color
36
+ def change_label_color(c)
37
+ @@label_color = Color.new(c)
38
+ end
39
+
40
+ ##
41
+ # Changes vertices color
42
+ def change_vertex_color(c)
43
+ @@vertex_color = Color.new(c)
44
+ end
45
+
46
+ ##
47
+ # Set the graph for visualization
48
+ def set_graph(graph)
49
+ if graph.class != OrientedGraph and graph.class != UnorientedGraph
50
+ raise ArgumentError, "Invalid graph type!"
51
+ end
52
+ clear_window
53
+ set_vertices(graph)
54
+ set_edges(graph)
55
+ set_labels(graph)
56
+ end
57
+
58
+ ##
59
+ # clear screen
60
+ def clear_window
61
+ Window.clear
62
+ end
63
+
64
+ ##
65
+ # close screen
66
+ def close_window
67
+ Window.close
68
+ end
69
+
70
+ ##
71
+ # show graph on the screen
72
+ def show_window
73
+ Window.show
74
+ end
75
+
76
+ ##
77
+ # radius of vertices circles
78
+ @@vert_radius = 15
79
+ ##
80
+ # width of the edges
81
+ @@line_width = 5
82
+ # size of labels
83
+ @@label_size = 15
84
+ ##
85
+ # color of labels
86
+ @@label_color = Color.new('red')
87
+ ##
88
+ # color of vertices
89
+ @@vertex_color = Color.new('white')
90
+
91
+ private
92
+
93
+ ##
94
+ # creates labels of edges and vertices
95
+ def set_labels(graph)
96
+ @v_labels = {}
97
+ graph.vertex_labels.keys.each do |v|
98
+ @v_labels[v] = draw_vertex_label(v, graph.vertex_labels[v])
99
+ end
100
+
101
+ @e_labels = {}
102
+ graph.edge_labels.keys.each do |pair|
103
+ @e_labels[pair] = draw_edge_label(pair, graph.edge_labels[pair])
104
+ end
105
+ end
106
+
107
+ ##
108
+ # draws label on vertex
109
+ def draw_vertex_label(v,label)
110
+ if (label.class != String and label.class != Integer)
111
+ return
112
+ end
113
+ x = @vertices[v].x - Math.sqrt(2)/2*@@vert_radius
114
+ y = @vertices[v].y - Math.sqrt(2)/2*@@vert_radius
115
+ return Text.new(label,x: x, y: y, size: @@label_size, color: @@label_color)
116
+ end
117
+
118
+ ##
119
+ # draws label on edge
120
+ def draw_edge_label(pair,label)
121
+ if (label.class != String and label.class != Integer)
122
+ return
123
+ end
124
+ x1 = @vertices[pair[:first]].x
125
+ y1 = @vertices[pair[:first]].y
126
+ x2 = @vertices[pair[:second]].x
127
+ y2 = @vertices[pair[:second]].y
128
+ x = (x1+x2)/2
129
+ y = (y1+y2)/2
130
+
131
+ if x1 == x2 and y1 == y2
132
+ x = @edges[pair][:line].x
133
+ y = @edges[pair][:line].y
134
+ end
135
+
136
+ return Text.new(label,x: x, y: y, size: @@label_size, color: @@label_color)
137
+ end
138
+
139
+ ##
140
+ # set all edges of the graph
141
+ def set_edges(graph)
142
+ @edges = {}
143
+ @is_oriented = graph.class == OrientedGraph
144
+ graph.vertices.keys.each do |from_vert|
145
+ graph.vertices[from_vert].each do |to_vert|
146
+ push_edge(from_vert,to_vert)
147
+ end
148
+ end
149
+ end
150
+
151
+ ##
152
+ # creates edge and push it to the @edges
153
+ def push_edge(from_vert, to_vert)
154
+ col = get_random_color
155
+ if @is_oriented and has_edge?(to_vert,from_vert)
156
+ col = @edges[Pair.new(to_vert,from_vert)][:line].color
157
+ end
158
+ arrow = @is_oriented ? draw_oriented_edge(from_vert,to_vert,col):draw_edge(from_vert,to_vert,col)
159
+ @edges[Pair.new(from_vert,to_vert)] = arrow
160
+ end
161
+
162
+ ##
163
+ # return true if graph contains current edge
164
+ def has_edge?(from_vert, to_vert)
165
+ if @is_oriented
166
+ return @edges.has_key?(Pair.new(from_vert,to_vert))
167
+ end
168
+ return (@edges.has_key?(Pair.new(to_vert,from_vert)) or @edges.has_key?(Pair.new(from_vert,to_vert)))
169
+ end
170
+
171
+ ##
172
+ # returns random color
173
+ def get_random_color
174
+ col = Color.new('random')
175
+ while (col == @@label_color) or (col == @@vertex_color)
176
+ col = Color.new('random')
177
+ end
178
+ return col
179
+ end
180
+
181
+ ##
182
+ # draws all vertices of the graph
183
+ def set_vertices(graph)
184
+ @vertices = {}
185
+ w = Window.get :width
186
+ h = Window.get :height
187
+ radius= [w,h].min*1.0 / 2 - @@vert_radius*4
188
+ vert_step = (360.0 / graph.vertex_number)*(Math::PI/180)
189
+ position = 0
190
+ graph.vertices.keys.each do |vert|
191
+ x = w/2 + Math.cos(position)*radius
192
+ y = h/2 + Math.sin(position)*radius
193
+ @vertices[vert] = draw_vertex(x,y)
194
+ position += vert_step
195
+ end
196
+ end
197
+
198
+ ##
199
+ # creates circle for vertex
200
+ def draw_vertex(x, y)
201
+ circle = Circle.new(x: x, y: y, radius: @@vert_radius, sectors: 128, color: @@vertex_color)
202
+ return circle
203
+ end
204
+
205
+ ##
206
+ # creates arrow of edge between vertices
207
+ def draw_oriented_edge(v1,v2,col)
208
+ line = draw_edge(v1,v2,col)
209
+
210
+ x1 = @vertices[v1].x
211
+ y1 = @vertices[v1].y
212
+ x2 = @vertices[v2].x
213
+ y2 = @vertices[v2].y
214
+
215
+ x_len = x2-x1
216
+ y_len = y2-y1
217
+ len = Math.sqrt(x_len*x_len+y_len*y_len)
218
+ sin = y_len/len
219
+ cos = x_len/len
220
+ pos_x1 = x2 - @@vert_radius*cos
221
+ pos_y1 = y2 - @@vert_radius*sin
222
+ height_x= pos_x1 - @@line_width*4*cos
223
+ height_y= pos_y1 - @@line_width*4*sin
224
+ sin, cos = cos, sin
225
+ pos_x2 = height_x + @@line_width*2*cos
226
+ pos_y3 = height_y + @@line_width*2*sin
227
+ pos_x3 = height_x - @@line_width*2*cos
228
+ pos_y2 = height_y - @@line_width*2*sin
229
+ #triangle = Circle.new(x: pos_x2, y: pos_y3,radius: 4, color: col)
230
+ #Circle.new(x: pos_x3, y: pos_y2,radius: 4, color: col)
231
+ triangle = Triangle.new(x1: pos_x1, y1: pos_y1, x2: pos_x2, y2: pos_y2, x3: pos_x3, y3: pos_y3, color: col)
232
+
233
+ return {line: line, triangle: triangle}
234
+ end
235
+
236
+ ##
237
+ # creates edge between vertices
238
+ def draw_edge(v1,v2,col)
239
+ x1 = @vertices[v1].x
240
+ y1 = @vertices[v1].y
241
+ x2 = @vertices[v2].x
242
+ y2 = @vertices[v2].y
243
+ x_len = x1-x2
244
+ y_len = y1-y2
245
+ len = Math.sqrt(x_len*x_len+y_len*y_len)
246
+
247
+ if len == 0
248
+ return draw_loop(v1,col)
249
+ end
250
+
251
+ sin = y_len/len
252
+ cos = x_len/len
253
+ pos_x0 = x1 - @@vert_radius*cos
254
+ pos_y0 = y1 - @@vert_radius*sin
255
+
256
+ x_len = x2-x1
257
+ y_len = y2-y1
258
+ sin = y_len/len
259
+ cos = x_len/len
260
+ pos_x1 = x2 - @@vert_radius*cos
261
+ pos_y1 = y2 - @@vert_radius*sin
262
+ return Line.new(x1: pos_x0, y1: pos_y0, x2: pos_x1, y2: pos_y1, width: @@line_width, color: col)
263
+ end
264
+
265
+ ##
266
+ # create loop edge
267
+ def draw_loop(v,col)
268
+ x = @vertices[v].x
269
+ y = @vertices[v].y
270
+ center_x = (Window.get :width) / 2
271
+ center_y = (Window.get :height) / 2
272
+ x_len = center_x-x
273
+ y_len = center_y-y
274
+ len = Math.sqrt(x_len*x_len+y_len*y_len)
275
+ sin = y_len/len
276
+ cos = x_len/len
277
+ pos_x1 = x - @@vert_radius*cos*2
278
+ pos_y1 = y - @@vert_radius*sin*2
279
+ circle = Circle.new(x: pos_x1, y: pos_y1, radius: @@vert_radius*2, color: col)
280
+ Circle.new(x: pos_x1, y: pos_y1, radius: @@vert_radius*2-@@line_width, color: Window.get( :background))
281
+ @vertices[v] = Circle.new(x: x, y: y, radius: @@vert_radius+1, color: @@vertex_color)
282
+ return circle
283
+ end
284
+
285
+ end
286
+ end
@@ -0,0 +1,181 @@
1
+ # Class represents computational graph
2
+ module BackPropogation
3
+ class ComputationalGraph
4
+
5
+ PRIORITY = Hash['(' => 0, '+' => 1, '-' => 1, '*' => 2, '/' => 2, '^' => 3]
6
+ TEMPLATES = {
7
+ operand: /^\s*([^\+\-\*\/\(\)\^\s]+)\s*(.*)/,
8
+ string: /^\s*([\+\-\*\/\^])\s*(.*)/,
9
+ brackets: /^\s*\(\s*(.*)/,
10
+ nested: /^\s*\)\s*(.*)/
11
+ }
12
+
13
+ attr_accessor :graph
14
+ def initialize(expr_s)
15
+ exprproc = ComputationalGraph::polish_parser(expr_s, [])
16
+ pregraph = []
17
+ @graph = []
18
+ exprproc.split.each do |elem|
19
+ case elem
20
+ when '+'
21
+ dot = ComputationalGates::SummGate.new(elem)
22
+ dot.connect(pregraph.pop,pregraph.pop)
23
+ when '*'
24
+ dot = ComputationalGates::MultGate.new(elem)
25
+ dot.connect(pregraph.pop,pregraph.pop)
26
+ when '/'
27
+ dot = ComputationalGates::DivGate.new(elem)
28
+ scnd = pregraph.pop
29
+ frst = pregraph.pop
30
+ dot.connect(frst,scnd)
31
+ else
32
+ dot = ComputationalGates::CompGate.new(elem)
33
+ end
34
+ pregraph.push(dot)
35
+ @graph.push(dot)
36
+ end
37
+ end
38
+ #Compute a value of expression
39
+ def forward_pass(variables_val)
40
+ @graph.each do |elem|
41
+ if elem.class != ComputationalGates::CompGate
42
+ elem.forward_pass
43
+ else
44
+ elem.frwrd = variables_val[elem.name]
45
+ end
46
+ end
47
+ graph.last.frwrd
48
+ end
49
+ #Compute a gradient value for inputs
50
+ def backward_pass(loss_value)
51
+ param_grad = Hash.new()
52
+ @graph.last.bckwrd = loss_value
53
+ @graph.reverse.each do |elem|
54
+ if elem.class != ComputationalGates::CompGate
55
+ elem.backward_pass
56
+ else
57
+ param_grad[elem.name] = elem.bckwrd
58
+ end
59
+ end
60
+ param_grad
61
+ end
62
+
63
+
64
+ def self.parse_operand(left, right, stack)
65
+ left + ' ' + polish_parser(right, stack)
66
+ end
67
+
68
+ def self.parse_string(left, right, i_str, stack)
69
+ if stack.empty? || PRIORITY[stack.last] < PRIORITY[left]
70
+ polish_parser(right, stack.push(left))
71
+ else
72
+ stack.pop + ' ' + polish_parser(i_str, stack)
73
+ end
74
+ end
75
+
76
+ def self.parse_nested(left, right, stack)
77
+ raise ArgumentError, 'Error: Excess of closing brackets.' if stack.empty?
78
+
79
+ head = stack.pop
80
+ PRIORITY[head].positive? ? head + ' ' + polish_parser(right, stack) : polish_parser(left, stack)
81
+ end
82
+
83
+ def self.parse_brackets(left, stack)
84
+ polish_parser(left, stack)
85
+ end
86
+
87
+ def self.parse_default(left, stack)
88
+ return '' if stack.empty?
89
+ raise ArgumentError, 'Error: Excess of opening brackets.' unless PRIORITY[stack.last] > 0
90
+
91
+ stack.pop + ' ' + polish_parser(left, stack)
92
+ end
93
+
94
+ #String preprocessing algorithm expression for computation
95
+ def self.polish_parser(i_str, stack)
96
+ case i_str
97
+ when TEMPLATES[:operand]
98
+ parse_operand(Regexp.last_match(1), Regexp.last_match(2), stack)
99
+ when TEMPLATES[:string]
100
+ parse_string(Regexp.last_match(1), Regexp.last_match(2), i_str, stack)
101
+ when TEMPLATES[:brackets]
102
+ parse_brackets(Regexp.last_match(1), stack.push('('))
103
+ when TEMPLATES[:nested]
104
+ parse_nested(Regexp.last_match(1), i_str, stack)
105
+ else
106
+ parse_default(i_str, stack)
107
+ end
108
+ end
109
+ end
110
+
111
+ module ComputationalGates
112
+ class CompGate
113
+ attr_accessor :frwrd,:bckwrd,:out,:name
114
+ def initialize(name)
115
+ @name = name
116
+ @frwrd = self
117
+ end
118
+ end
119
+ class SummGate < CompGate
120
+ attr_accessor :in_frst,:in_scnd
121
+ def initialize(name)
122
+ super(name)
123
+ end
124
+ def connect(f_n,s_n)
125
+ @in_frst = f_n
126
+ @in_scnd = s_n
127
+ f_n.out = self
128
+ s_n.out = self
129
+ end
130
+
131
+ def forward_pass()
132
+ @frwrd = @in_frst.frwrd + @in_scnd.frwrd
133
+ end
134
+ def backward_pass()
135
+ @in_frst.bckwrd = @bckwrd
136
+ @in_scnd.bckwrd = @bckwrd
137
+ end
138
+
139
+ end
140
+ class MultGate < CompGate
141
+ attr_accessor :in_frst,:in_scnd
142
+ def initialize(name)
143
+ super(name)
144
+ end
145
+ def connect(f_n,s_n)
146
+ @in_frst = f_n
147
+ @in_scnd = s_n
148
+ f_n.out = self
149
+ s_n.out = self
150
+ end
151
+ def forward_pass()
152
+ @frwrd = @in_frst.frwrd * @in_scnd.frwrd
153
+ end
154
+ def backward_pass()
155
+ @in_frst.bckwrd = @bckwrd * @in_scnd.frwrd
156
+ @in_scnd.bckwrd = @bckwrd * @in_frst.frwrd
157
+ end
158
+
159
+ end
160
+ class DivGate < CompGate
161
+ attr_accessor :in_frst,:in_scnd
162
+ def initialize(name)
163
+ super(name)
164
+ end
165
+ def connect(f_n,s_n)
166
+ @in_frst = f_n
167
+ @in_scnd = s_n
168
+ f_n.out = self
169
+ s_n.out = self
170
+ end
171
+ def forward_pass()
172
+ @frwrd = @in_frst.frwrd / @in_scnd.frwrd
173
+ end
174
+ def backward_pass()
175
+ @in_frst.bckwrd = @bckwrd * ((-1)/(@in_scnd.frwrd ** 2))
176
+ @in_scnd.bckwrd = @bckwrd * ((-1)/(@in_frst.frwrd ** 2))
177
+ end
178
+
179
+ end
180
+ end
181
+ end