silicium 0.0.20 → 0.0.21

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