silicium 0.0.20 → 0.0.21

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