silicium 0.0.14 → 0.0.22
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.codeclimate.yml +4 -0
- data/.gitignore +13 -11
- data/.rakeTasks +8 -0
- data/.travis.yml +17 -3
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +8 -4
- data/LICENSE.txt +21 -21
- data/Makefile +269 -0
- data/README.md +588 -44
- data/Rakefile +17 -10
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/docs/Object.html +117 -0
- data/docs/README_md.html +142 -0
- data/docs/Silicium/Combinatorics.html +270 -0
- data/docs/Silicium/Dice/Polyhedron.html +315 -0
- data/docs/Silicium/Dice/PolyhedronSet.html +321 -0
- data/docs/Silicium/Dice.html +99 -0
- data/docs/Silicium/Error.html +106 -0
- data/docs/Silicium/Geometry/Line2dCanon.html +243 -0
- data/docs/Silicium/Geometry/VariablesOrderException.html +106 -0
- data/docs/Silicium/Geometry.html +940 -0
- data/docs/Silicium/GraphVisualizer.html +226 -0
- data/docs/Silicium/Graphs/GraphError.html +106 -0
- data/docs/Silicium/Graphs/OrientedGraph.html +901 -0
- data/docs/Silicium/Graphs/UnorientedGraph.html +237 -0
- data/docs/Silicium/Graphs.html +374 -0
- data/docs/Silicium/IntegralDoesntExistError.html +106 -0
- data/docs/Silicium/NumericalIntegration.html +521 -0
- data/docs/Silicium/Optimization.html +629 -0
- data/docs/Silicium/Plotter/Image.html +297 -0
- data/docs/Silicium/Plotter.html +186 -0
- data/docs/Silicium.html +101 -0
- data/docs/created.rid +9 -0
- data/docs/css/fonts.css +167 -0
- data/docs/css/rdoc.css +619 -0
- data/docs/fonts/Lato-Light.ttf +0 -0
- data/docs/fonts/Lato-LightItalic.ttf +0 -0
- data/docs/fonts/Lato-Regular.ttf +0 -0
- data/docs/fonts/Lato-RegularItalic.ttf +0 -0
- data/docs/fonts/SourceCodePro-Bold.ttf +0 -0
- data/docs/fonts/SourceCodePro-Regular.ttf +0 -0
- data/docs/images/add.png +0 -0
- data/docs/images/arrow_up.png +0 -0
- data/docs/images/brick.png +0 -0
- data/docs/images/brick_link.png +0 -0
- data/docs/images/bug.png +0 -0
- data/docs/images/bullet_black.png +0 -0
- data/docs/images/bullet_toggle_minus.png +0 -0
- data/docs/images/bullet_toggle_plus.png +0 -0
- data/docs/images/date.png +0 -0
- data/docs/images/delete.png +0 -0
- data/docs/images/find.png +0 -0
- data/docs/images/loadingAnimation.gif +0 -0
- data/docs/images/macFFBgHack.png +0 -0
- data/docs/images/package.png +0 -0
- data/docs/images/page_green.png +0 -0
- data/docs/images/page_white_text.png +0 -0
- data/docs/images/page_white_width.png +0 -0
- data/docs/images/plugin.png +0 -0
- data/docs/images/ruby.png +0 -0
- data/docs/images/tag_blue.png +0 -0
- data/docs/images/tag_green.png +0 -0
- data/docs/images/transparent.png +0 -0
- data/docs/images/wrench.png +0 -0
- data/docs/images/wrench_orange.png +0 -0
- data/docs/images/zoom.png +0 -0
- data/docs/index.html +134 -0
- data/docs/js/darkfish.js +84 -0
- data/docs/js/navigation.js +105 -0
- data/docs/js/navigation.js.gz +0 -0
- data/docs/js/search.js +110 -0
- data/docs/js/search_index.js +1 -0
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js +229 -0
- data/docs/js/searcher.js.gz +0 -0
- data/docs/table_of_contents.html +697 -0
- data/lib/algebra.rb +452 -0
- data/lib/algebra_diff.rb +258 -0
- data/lib/geometry/figure.rb +62 -0
- data/lib/geometry.rb +290 -0
- data/lib/geometry3d.rb +270 -0
- data/lib/graph/dfs.rb +41 -0
- data/lib/graph/kruskal.rb +36 -0
- data/lib/graph/scc.rb +97 -0
- data/lib/graph.rb +350 -0
- data/lib/graph_visualizer.rb +286 -0
- data/lib/ml_algorithms.rb +181 -0
- data/lib/numerical_integration.rb +184 -0
- data/lib/optimization.rb +208 -0
- data/lib/plotter.rb +258 -0
- data/lib/polynomial_division.rb +132 -0
- data/lib/polynomial_interpolation.rb +94 -0
- data/lib/regression.rb +120 -0
- data/lib/silicium/adding.rb +37 -0
- data/lib/silicium/conversions.rb +23 -0
- data/lib/silicium/multi.rb +82 -0
- data/lib/silicium/sparse.rb +76 -0
- data/lib/silicium/sugar.rb +37 -0
- data/lib/silicium/trans.rb +26 -0
- data/lib/silicium/version.rb +3 -3
- data/lib/silicium.rb +29 -6
- data/lib/theory_of_probability.rb +240 -0
- data/lib/topological_sort.rb +50 -0
- data/oriented_graph.png +0 -0
- data/plot.png +0 -0
- data/silicium.gemspec +4 -3
- 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
|