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.
- checksums.yaml +4 -4
- data/.codeclimate.yml +3 -3
- data/.gitignore +13 -13
- data/.rakeTasks +8 -0
- data/.travis.yml +28 -25
- data/CODE_OF_CONDUCT.md +74 -74
- data/Gemfile +8 -8
- data/LICENSE.txt +21 -21
- data/Makefile +269 -269
- data/README.md +588 -46
- data/Rakefile +16 -16
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/docs/Object.html +117 -117
- data/docs/README_md.html +142 -142
- data/docs/Silicium/Combinatorics.html +270 -270
- data/docs/Silicium/Dice/Polyhedron.html +315 -315
- data/docs/Silicium/Dice/PolyhedronSet.html +321 -321
- data/docs/Silicium/Dice.html +99 -99
- data/docs/Silicium/Error.html +106 -106
- data/docs/Silicium/Geometry/Line2dCanon.html +243 -243
- data/docs/Silicium/Geometry/VariablesOrderException.html +106 -106
- data/docs/Silicium/Geometry.html +940 -940
- data/docs/Silicium/GraphVisualizer.html +226 -0
- data/docs/Silicium/Graphs/GraphError.html +106 -106
- data/docs/Silicium/Graphs/OrientedGraph.html +901 -775
- data/docs/Silicium/Graphs/UnorientedGraph.html +237 -284
- data/docs/Silicium/Graphs.html +374 -164
- data/docs/Silicium/IntegralDoesntExistError.html +106 -106
- data/docs/Silicium/NumericalIntegration.html +521 -521
- data/docs/Silicium/Optimization.html +629 -639
- data/docs/Silicium/Plotter/Image.html +297 -297
- data/docs/Silicium/Plotter.html +186 -186
- data/docs/Silicium.html +101 -101
- data/docs/created.rid +9 -9
- data/docs/css/fonts.css +167 -167
- data/docs/css/rdoc.css +619 -619
- data/docs/index.html +134 -132
- data/docs/js/darkfish.js +84 -84
- data/docs/js/navigation.js +105 -105
- data/docs/js/search.js +110 -110
- data/docs/js/search_index.js +1 -1
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js +229 -229
- data/docs/table_of_contents.html +697 -608
- 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 -236
- data/lib/geometry3d.rb +270 -0
- data/lib/graph/dfs.rb +42 -0
- data/lib/graph/kruskal.rb +36 -0
- data/lib/graph/scc.rb +97 -0
- data/lib/graph.rb +350 -164
- data/lib/graph_visualizer.rb +287 -0
- data/lib/ml_algorithms.rb +181 -0
- data/lib/numerical_integration.rb +184 -147
- data/lib/optimization.rb +209 -144
- data/lib/plotter.rb +256 -96
- 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 +5 -5
- data/lib/theory_of_probability.rb +240 -226
- data/lib/topological_sort.rb +50 -0
- data/oriented_graph.png +0 -0
- data/plot.png +0 -0
- data/silicium.gemspec +38 -39
- metadata +38 -16
data/lib/graph.rb
CHANGED
@@ -1,164 +1,350 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
@vertex_labels = {}
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
def
|
31
|
-
if @vertices.has_key?(
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
def
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
@
|
65
|
-
end
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
@
|
85
|
-
end
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
def
|
100
|
-
@
|
101
|
-
end
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
def
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
#
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
1
|
+
require_relative 'graph/dfs'
|
2
|
+
require_relative 'graph/scc'
|
3
|
+
require_relative 'graph/kruskal'
|
4
|
+
|
5
|
+
module Silicium
|
6
|
+
module Graphs
|
7
|
+
Pair = Struct.new(:first, :second)
|
8
|
+
|
9
|
+
class GraphError < Error
|
10
|
+
end
|
11
|
+
|
12
|
+
##
|
13
|
+
# Class represents oriented graph
|
14
|
+
class OrientedGraph
|
15
|
+
def initialize(initializer = [])
|
16
|
+
@vertices = {}; @vertex_labels = {}
|
17
|
+
@edge_labels = {}; @edge_number = 0
|
18
|
+
initializer.each do |v|
|
19
|
+
add_vertex!(v[:v])
|
20
|
+
v[:i].each do |iv|
|
21
|
+
add_vertex!(v[:v])
|
22
|
+
add_vertex!(iv)
|
23
|
+
add_edge!(v[:v], iv)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
##
|
29
|
+
# Adds vertex to graph
|
30
|
+
def add_vertex!(vertex_id)
|
31
|
+
if @vertices.has_key?(vertex_id); return end
|
32
|
+
@vertices[vertex_id] = [].to_set
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Adds edge to graph
|
37
|
+
def add_edge!(from, to)
|
38
|
+
protected_add_edge!(from, to)
|
39
|
+
@edge_number += 1
|
40
|
+
end
|
41
|
+
|
42
|
+
# should only be used in constructor
|
43
|
+
def add_edge_force!(from, to)
|
44
|
+
add_vertex!(from)
|
45
|
+
add_vertex!(to)
|
46
|
+
add_edge!(from, to)
|
47
|
+
end
|
48
|
+
|
49
|
+
##
|
50
|
+
# Returns array of vertices which adjacted with vertex
|
51
|
+
# @raise [GraphError] if graph does not contain vertex
|
52
|
+
def adjacted_with(vertex)
|
53
|
+
raise GraphError.new("Graph does not contain vertex #{vertex}") unless @vertices.has_key?(vertex)
|
54
|
+
@vertices[vertex].clone
|
55
|
+
end
|
56
|
+
|
57
|
+
##
|
58
|
+
# Adds label to edge
|
59
|
+
# @raise [GraphError] if graph does not contain edge
|
60
|
+
def label_edge!(from, to, label)
|
61
|
+
unless @vertices.has_key?(from) && @vertices[from].include?(to)
|
62
|
+
raise GraphError.new("Graph does not contain edge (#{from}, #{to})")
|
63
|
+
end
|
64
|
+
@edge_labels[Pair.new(from, to)] = label
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# Adds label to vertex
|
69
|
+
# @raise [GraphError] if graph does not contain vertex
|
70
|
+
def label_vertex!(vertex, label)
|
71
|
+
unless @vertices.has_key?(vertex)
|
72
|
+
raise GraphError.new("Graph does not contain vertex #{vertex}")
|
73
|
+
end
|
74
|
+
@vertex_labels[vertex] = label
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Returns edge label
|
79
|
+
# @raise [GraphError] if graph does not contain edge
|
80
|
+
def get_edge_label(from, to)
|
81
|
+
if !@vertices.has_key?(from) || ! @vertices[from].include?(to)
|
82
|
+
raise GraphError.new("Graph does not contain edge (#{from}, #{to})")
|
83
|
+
end
|
84
|
+
@edge_labels[Pair.new(from, to)]
|
85
|
+
end
|
86
|
+
|
87
|
+
##
|
88
|
+
# Returns vertex label
|
89
|
+
# @raise [GraphError] if graph does not contain vertex
|
90
|
+
def get_vertex_label(vertex)
|
91
|
+
unless @vertices.has_key?(vertex)
|
92
|
+
raise GraphError.new("Graph does not contain vertex #{vertex}")
|
93
|
+
end
|
94
|
+
|
95
|
+
@vertex_labels[vertex]
|
96
|
+
end
|
97
|
+
##
|
98
|
+
# Returns number of vertices
|
99
|
+
def vertex_number
|
100
|
+
@vertices.count
|
101
|
+
end
|
102
|
+
##
|
103
|
+
# Returns number of edges
|
104
|
+
def edge_number
|
105
|
+
@edge_number
|
106
|
+
end
|
107
|
+
##
|
108
|
+
# Returns number of vertex labels
|
109
|
+
def vertex_label_number
|
110
|
+
@vertex_labels.count
|
111
|
+
end
|
112
|
+
##
|
113
|
+
# Returns number of edge labels
|
114
|
+
def edge_label_number
|
115
|
+
@edge_labels.count
|
116
|
+
end
|
117
|
+
##
|
118
|
+
# Checks if graph contains vertex
|
119
|
+
def has_vertex?(vertex)
|
120
|
+
@vertices.has_key?(vertex)
|
121
|
+
end
|
122
|
+
##
|
123
|
+
# Checks if graph contains edge
|
124
|
+
def has_edge?(from, to)
|
125
|
+
@vertices.has_key?(from) && @vertices[from].include?(to)
|
126
|
+
end
|
127
|
+
##
|
128
|
+
# Deletes vertex from graph
|
129
|
+
def delete_vertex!(vertex)
|
130
|
+
if has_vertex?(vertex)
|
131
|
+
@vertices.keys.each { |key| delete_edge!(key, vertex) }
|
132
|
+
@vertices.delete(vertex)
|
133
|
+
@vertex_labels.delete(vertex)
|
134
|
+
@vertices.keys.each { |key| @edge_labels.delete(Pair.new(vertex, key)) }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
##
|
138
|
+
# Deletes edge from graph
|
139
|
+
def delete_edge!(from, to)
|
140
|
+
protected_delete_edge!(from, to)
|
141
|
+
@edge_number -= 1
|
142
|
+
end
|
143
|
+
##
|
144
|
+
# Reverses graph
|
145
|
+
def reverse!
|
146
|
+
l = {}; v = {}
|
147
|
+
@vertices.keys.each { |from| v[from] = [].to_set }
|
148
|
+
@vertices.keys.each do |from|
|
149
|
+
@vertices[from].each do |to|
|
150
|
+
v[to] << from
|
151
|
+
if @edge_labels.include?(Pair.new(from, to))
|
152
|
+
l[Pair.new(to, from)] = @edge_labels[Pair.new(from, to)]
|
153
|
+
end
|
154
|
+
end
|
155
|
+
end
|
156
|
+
@vertices = v; @edge_labels = l
|
157
|
+
end
|
158
|
+
|
159
|
+
|
160
|
+
# Returns array of vertices
|
161
|
+
def vertices
|
162
|
+
@vertices
|
163
|
+
end
|
164
|
+
|
165
|
+
# Returns labels of edges
|
166
|
+
def edge_labels
|
167
|
+
@edge_labels
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
# Returns labels of vertices
|
172
|
+
def vertex_labels
|
173
|
+
@vertex_labels
|
174
|
+
end
|
175
|
+
|
176
|
+
protected
|
177
|
+
##
|
178
|
+
# Adds edge to graph
|
179
|
+
def protected_add_edge!(from, to)
|
180
|
+
@vertices[from] << to if @vertices.has_key?(from) && @vertices.has_key?(to)
|
181
|
+
end
|
182
|
+
##
|
183
|
+
# Deletes edge from graph
|
184
|
+
def protected_delete_edge!(from, to)
|
185
|
+
if has_edge?(from, to)
|
186
|
+
@vertices[from].delete(to)
|
187
|
+
@edge_labels.delete(Pair.new(from, to))
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
##
|
193
|
+
# Class represents unoriented graph
|
194
|
+
class UnorientedGraph < OrientedGraph
|
195
|
+
##
|
196
|
+
# Adds edge to graph
|
197
|
+
def add_edge!(from, to)
|
198
|
+
protected_add_edge!(from, to)
|
199
|
+
protected_add_edge!(to, from)
|
200
|
+
@edge_number += 1
|
201
|
+
end
|
202
|
+
##
|
203
|
+
# Adds label to edge
|
204
|
+
def label_edge!(from, to, label)
|
205
|
+
super(from, to, label)
|
206
|
+
super(to, from, label)
|
207
|
+
end
|
208
|
+
##
|
209
|
+
# Deletes edge from graph
|
210
|
+
def delete_edge!(from, to)
|
211
|
+
protected_delete_edge!(from, to)
|
212
|
+
protected_delete_edge!(to, from)
|
213
|
+
@edge_number -= 1
|
214
|
+
end
|
215
|
+
|
216
|
+
end
|
217
|
+
##
|
218
|
+
# Implements breadth-first search (BFS)
|
219
|
+
def breadth_first_search?(graph, start, goal)
|
220
|
+
visited = Hash.new(false)
|
221
|
+
queue = Queue.new
|
222
|
+
queue.push(start)
|
223
|
+
visited[start] = true
|
224
|
+
until queue.empty? do
|
225
|
+
node = queue.pop
|
226
|
+
return true if node == goal
|
227
|
+
add_to_queue(graph, queue, node, visited)
|
228
|
+
end
|
229
|
+
false
|
230
|
+
end
|
231
|
+
##
|
232
|
+
# Adds to queue not visited vertices
|
233
|
+
def add_to_queue(graph, queue, node, visited)
|
234
|
+
graph.vertices[node].each do |child|
|
235
|
+
unless visited[child]
|
236
|
+
queue.push(child)
|
237
|
+
visited[child] = true
|
238
|
+
end
|
239
|
+
end
|
240
|
+
end
|
241
|
+
##
|
242
|
+
# Checks if graph is connected
|
243
|
+
def connected?(graph)
|
244
|
+
start = graph.vertices.keys[0]
|
245
|
+
goal = graph.vertices.keys[graph.vertex_number - 1]
|
246
|
+
pred = breadth_first_search?(graph, start, goal)
|
247
|
+
graph.reverse!
|
248
|
+
pred = pred and breadth_first_search?(graph, goal, start)
|
249
|
+
graph.reverse!
|
250
|
+
pred
|
251
|
+
end
|
252
|
+
##
|
253
|
+
# Returns number of connected vertices
|
254
|
+
def number_of_connected(graph)
|
255
|
+
visited = Hash.new(false)
|
256
|
+
res = 0
|
257
|
+
graph.vertices.keys.each do |v|
|
258
|
+
unless visited[v]
|
259
|
+
dfu(graph, v, visited)
|
260
|
+
res += 1
|
261
|
+
end
|
262
|
+
end
|
263
|
+
res
|
264
|
+
end
|
265
|
+
##
|
266
|
+
# Passes graph's vertices and marks them visited
|
267
|
+
def dfu(graph, vertice, visited)
|
268
|
+
visited[vertice] = true
|
269
|
+
graph.vertices[vertice].each { |item| dfu(graph, item, visited) unless visited[item] }
|
270
|
+
end
|
271
|
+
|
272
|
+
def add_edge!(mst, edge, label)
|
273
|
+
mst.add_vertex!(edge[0])
|
274
|
+
mst.add_vertex!(edge[1])
|
275
|
+
mst.add_edge!(edge[0], edge[1])
|
276
|
+
mst.label_edge!(edge[0], edge[1], label)
|
277
|
+
end
|
278
|
+
|
279
|
+
|
280
|
+
|
281
|
+
##
|
282
|
+
# "Split" graph into elements like :[from, to] = label
|
283
|
+
def graph_to_sets(graph)
|
284
|
+
labels = {}
|
285
|
+
graph.vertices.keys.each do |from|
|
286
|
+
graph.adjacted_with(from).each { |to| labels[Pair.new(from, to)] = graph.get_edge_label(from, to) }
|
287
|
+
end
|
288
|
+
labels.to_set.sort_by { |elem| elem[1] }.to_h
|
289
|
+
end
|
290
|
+
|
291
|
+
def sum_labels(graph)
|
292
|
+
labels = 0
|
293
|
+
graph.vertices.keys.each do |from|
|
294
|
+
graph.adjacted_with(from).each { |to| labels += graph.get_edge_label(from, to) }
|
295
|
+
end
|
296
|
+
labels / 2
|
297
|
+
end
|
298
|
+
|
299
|
+
|
300
|
+
|
301
|
+
##
|
302
|
+
# Implements algorithm of Dijkstra
|
303
|
+
def dijkstra_algorithm(graph, starting_vertex)
|
304
|
+
if !graph.has_vertex?(starting_vertex)
|
305
|
+
raise GraphError.new("Graph does not contains vertex #{starting_vertex}")
|
306
|
+
end
|
307
|
+
unvisited_vertices = graph.vertices.clone.to_a
|
308
|
+
labels = {}
|
309
|
+
paths = {}
|
310
|
+
initialize_labels_and_paths(graph, labels,paths,starting_vertex)
|
311
|
+
while unvisited_vertices.size > 0
|
312
|
+
unvisited_vertices.sort { |a, b| compare_labels(a, b, labels) }
|
313
|
+
vertex = unvisited_vertices.first
|
314
|
+
vertex[1].each do |adj|
|
315
|
+
new_label = labels[vertex[0]] + graph.get_edge_label(vertex[0], adj)
|
316
|
+
if change_label?(labels[adj], new_label)
|
317
|
+
labels[adj] = new_label
|
318
|
+
paths[adj] = paths[vertex[0]].clone
|
319
|
+
paths[adj].push adj
|
320
|
+
end
|
321
|
+
end
|
322
|
+
unvisited_vertices.delete_at(0)
|
323
|
+
end
|
324
|
+
{"labels" => labels, "paths" => paths}
|
325
|
+
end
|
326
|
+
|
327
|
+
private
|
328
|
+
|
329
|
+
def initialize_labels_and_paths(graph, labels,paths,starting_vertex)
|
330
|
+
graph.vertices.each_key do |vertex|
|
331
|
+
labels[vertex] = -1
|
332
|
+
paths[vertex] = [starting_vertex]
|
333
|
+
end
|
334
|
+
labels[starting_vertex] = 0
|
335
|
+
end
|
336
|
+
|
337
|
+
def compare_labels(a, b, labels)
|
338
|
+
return -1 if labels[b[0]] == -1
|
339
|
+
return 1 if labels[a[0]] == -1
|
340
|
+
return labels[a[0]] <=> labels[b[0]]
|
341
|
+
end
|
342
|
+
|
343
|
+
def change_label?(label, new_label)
|
344
|
+
return true if label == -1
|
345
|
+
return false if new_label == -1
|
346
|
+
return new_label < label
|
347
|
+
end
|
348
|
+
|
349
|
+
end
|
350
|
+
end
|