silicium 0.0.2 → 0.0.21
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -0,0 +1,94 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Algebra
|
3
|
+
|
4
|
+
##
|
5
|
+
# A class providing polynomial interpolation methods
|
6
|
+
class PolynomialInterpolation
|
7
|
+
|
8
|
+
##
|
9
|
+
# x : array of data points
|
10
|
+
# y : array returned by function
|
11
|
+
# z : the node to interpolate
|
12
|
+
def self.lagrange_polynomials(x , y , z )
|
13
|
+
check_variables(x, y, z)
|
14
|
+
result = 0.0
|
15
|
+
y.each_index do |j|
|
16
|
+
p1 = 1.0
|
17
|
+
p2 = 1.0
|
18
|
+
x.each_index do |i|
|
19
|
+
if i != j
|
20
|
+
p1 = p1 * (z - x[i])
|
21
|
+
p2 = p2 * (x[j] - x[i])
|
22
|
+
end
|
23
|
+
end
|
24
|
+
result = result + y[j] * p1 / p2
|
25
|
+
end
|
26
|
+
result
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# x : array of data points
|
31
|
+
# y : array returned by function
|
32
|
+
# r : the node to interpolate
|
33
|
+
def self.newton_polynomials(x, y, r)
|
34
|
+
check_variables(x, y, r)
|
35
|
+
a = Array[]
|
36
|
+
y.each do |elem|
|
37
|
+
a << elem
|
38
|
+
end
|
39
|
+
for j in 1..x.length - 1
|
40
|
+
i = x.length - 1
|
41
|
+
while i != j - 1
|
42
|
+
a[i] = (a[i] - a[i - 1]) / (x[i] - x[i - j])
|
43
|
+
i -= 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
n = a.length - 1
|
48
|
+
res = a[n]
|
49
|
+
i = n - 1
|
50
|
+
while i != -1
|
51
|
+
res = res * (r - x[i]) + a[i]
|
52
|
+
i -= 1
|
53
|
+
end
|
54
|
+
res
|
55
|
+
end
|
56
|
+
|
57
|
+
# helper
|
58
|
+
def self.check_variables(x, y, z)
|
59
|
+
check_types(x, y, z)
|
60
|
+
check_arrays(x, y)
|
61
|
+
end
|
62
|
+
|
63
|
+
#helper for helper
|
64
|
+
def self.check_arrays(x, y)
|
65
|
+
|
66
|
+
if x.size < 2 || x.size < 2
|
67
|
+
raise ArgumentError, 'Arrays are too small'
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
#helper for helper
|
73
|
+
def self.check_types(x, y, z)
|
74
|
+
|
75
|
+
if x.class != Array || y.class != Array
|
76
|
+
raise ArgumentError, 'Wrong type of variables x or y'
|
77
|
+
end
|
78
|
+
|
79
|
+
if z.class.superclass != Numeric
|
80
|
+
raise ArgumentError, 'Wrong type of variable z'
|
81
|
+
end
|
82
|
+
|
83
|
+
if x[0].class.superclass != Numeric || y[0].class.superclass != Numeric
|
84
|
+
raise ArgumentError, 'Wrong type of arrays'
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
data/lib/regression.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Regression
|
3
|
+
class LinearRegressionByGradientDescent
|
4
|
+
# Finds parameters theta0, theta1 for equation theta0 + theta1 * x
|
5
|
+
# for linear regression of given plot of one variable
|
6
|
+
# @param plot Actually hash x => y for different points of the plot
|
7
|
+
# @param alpha Speed of learning (should be little enough not to diverge)
|
8
|
+
# @param start_theta0 Starting value of theta0
|
9
|
+
# @param start_theta1 Starting value of theta1
|
10
|
+
# @return [Numeric] theta0, theta1
|
11
|
+
def self.generate_function(plot, alpha = 0.01, start_theta0 = 0.0, start_theta1 = 0.0)
|
12
|
+
theta0 = start_theta0
|
13
|
+
theta1 = start_theta1
|
14
|
+
m = plot.length.to_f
|
15
|
+
epsilon = 0.000001
|
16
|
+
bias_new = 5.0
|
17
|
+
while bias_new.abs() > epsilon
|
18
|
+
old_theta0, old_theta1 = theta0, theta1
|
19
|
+
oth = theta0
|
20
|
+
theta0 = theta0 - alpha / m * d_dt_for_theta0(plot, theta0, theta1)
|
21
|
+
theta1 = theta1 - alpha / m * d_dt_for_theta1(plot, oth, theta1)
|
22
|
+
bias_new = [(theta0 - old_theta0).abs(), (theta1 - old_theta1).abs()].max()
|
23
|
+
end
|
24
|
+
return theta0, theta1
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def self.d_dt_for_theta0(plot, theta0, theta1)
|
30
|
+
result = 0.0
|
31
|
+
plot.each { |x, y| result += (theta0 + theta1 * x) - y }
|
32
|
+
|
33
|
+
result
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.d_dt_for_theta1(plot, theta0, theta1)
|
37
|
+
result = 0
|
38
|
+
plot.each { |x, y| result += ((theta0 + theta1 * x) - y) * x }
|
39
|
+
|
40
|
+
result
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
# Finds parameters as array [1..n] for polynom of n-th degree
|
46
|
+
# @param plot Actually hash x => y for different points of the plot
|
47
|
+
# @param n Degree of expected polynom
|
48
|
+
# @param alpha Speed of learning (should be little enough not to diverge)
|
49
|
+
# @param epsilon Accuracy
|
50
|
+
# @return Array[Numeric] coefficients (little index is lower degree parameter)
|
51
|
+
class PolynomialRegressionByGradientDescent
|
52
|
+
def self.generate_function(given_plot, n = 5, alpha = 0.001, epsilon = 0.000001)
|
53
|
+
scaling = n > 3
|
54
|
+
if scaling
|
55
|
+
plot, avg_x, div = feature_scaled_plot(given_plot, n)
|
56
|
+
else
|
57
|
+
(plot = given_plot)
|
58
|
+
end
|
59
|
+
array = Array.new(n + 1, 1)
|
60
|
+
m = plot.length.to_f
|
61
|
+
bias = old_bias = 0.5
|
62
|
+
|
63
|
+
array = calculate([bias, epsilon, array, alpha, plot, old_bias, m])
|
64
|
+
|
65
|
+
return array.map! {|x| x * div + avg_x } if scaling
|
66
|
+
array
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def self.calculate(params)
|
72
|
+
while params[0].abs() > params[1]
|
73
|
+
old_array = params[2].dup()
|
74
|
+
i = -1
|
75
|
+
params[2].map! { |elem|
|
76
|
+
i += 1
|
77
|
+
elem - params[3] / params[6] * d_dt(params[4], old_array, i)
|
78
|
+
}
|
79
|
+
params[0] = (params[2].zip(old_array).map {|new, old| (new - old).abs()}).max()
|
80
|
+
raise "Divergence" if params[0] > params[5]
|
81
|
+
params[5] = params[0]
|
82
|
+
end
|
83
|
+
params[2]
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.d_dt(plot, old_array, i)
|
87
|
+
sum = 0.0
|
88
|
+
plot.each { |x, y| sum += (func(old_array, x) - y) * (i + 1) * (x ** i) }
|
89
|
+
|
90
|
+
sum
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.func(array, x)
|
94
|
+
sum = 0.0
|
95
|
+
i = 0
|
96
|
+
array.each do |elem|
|
97
|
+
sum += elem * (x ** i)
|
98
|
+
i += 1
|
99
|
+
end
|
100
|
+
sum
|
101
|
+
end
|
102
|
+
|
103
|
+
def self.feature_scaled_plot(given_plot, n)
|
104
|
+
max_x = given_plot[0][0]
|
105
|
+
min_x = given_plot[0][0]
|
106
|
+
sum_x = 0.0
|
107
|
+
given_plot.each do |x, _|
|
108
|
+
max_x = x if x > max_x
|
109
|
+
min_x = x if x < min_x
|
110
|
+
sum_x += x
|
111
|
+
end
|
112
|
+
avg_x = sum_x.to_f / given_plot.length
|
113
|
+
range_x = max_x - min_x
|
114
|
+
div = range_x ** n
|
115
|
+
new_plot = given_plot.map {|x, y| [x, (y.to_f - avg_x) / div]}
|
116
|
+
return new_plot, avg_x, div
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Sparse
|
3
|
+
# addition for SparseMatrix class
|
4
|
+
class SparseMatrix
|
5
|
+
##
|
6
|
+
# @param [SparseMatrix] matrix - second matrix for adding
|
7
|
+
# @raise [ArgumentError] If the size of the first matrix doesn't
|
8
|
+
# match the size of the second matrix
|
9
|
+
# @return [SparseMatrix] Matrix as the sum of the other two matrices
|
10
|
+
#
|
11
|
+
# Makes the sum of two matrix
|
12
|
+
def adding(matrix)
|
13
|
+
raise 'wrong argument' if @n != matrix.m
|
14
|
+
|
15
|
+
res = SparseMatrix.new(@n, @m)
|
16
|
+
(0..@n).each { |i|
|
17
|
+
help_row1 = get_row(i)
|
18
|
+
help_row2 = matrix.get_row(i)
|
19
|
+
res_row = Array.new(@m, 0)
|
20
|
+
j = 0
|
21
|
+
help_row1.each do |elem|
|
22
|
+
res_row[j] = elem + help_row2[j]
|
23
|
+
j = j + 1
|
24
|
+
end
|
25
|
+
k = 0
|
26
|
+
res_row.each do |elem|
|
27
|
+
if (elem != 0)
|
28
|
+
res.add(i, k, elem)
|
29
|
+
end
|
30
|
+
k = k+1
|
31
|
+
end
|
32
|
+
}
|
33
|
+
res
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Sparse
|
3
|
+
# here goes the Sparse class
|
4
|
+
class SparseMatrix
|
5
|
+
# #
|
6
|
+
# A static method for initializing sparse matrix from a regular one
|
7
|
+
# @param [Array] mat - Source matrix for conversion
|
8
|
+
def self.sparse(mat)
|
9
|
+
new = SparseMatrix.new(mat.count, mat[0].count)
|
10
|
+
i = 0
|
11
|
+
mat.each do |row|
|
12
|
+
j = 0
|
13
|
+
row.each do |elem|
|
14
|
+
new.add(i, j, elem) unless elem.zero?
|
15
|
+
j += 1
|
16
|
+
end
|
17
|
+
i += 1
|
18
|
+
end
|
19
|
+
new
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Sparse
|
3
|
+
# here goes tha addition to SparseMatrix class
|
4
|
+
class SparseMatrix
|
5
|
+
##
|
6
|
+
# @param [Integer] pos - Position of a row to return
|
7
|
+
# @raise [ArgumentError] if position was less or bigger than count of cols
|
8
|
+
# @return [Array] The array contains elements of row
|
9
|
+
#
|
10
|
+
# Returns a row of sparse matrix by its position
|
11
|
+
def get_row(pos)
|
12
|
+
get_dimension({dimension: 0, position: 1}, pos)
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# @param [Integer] pos - Position of a column to return
|
17
|
+
# @raise [ArgumentError] if position was less or bigger than count of rows
|
18
|
+
# @return [Array] The array that contains elements of column
|
19
|
+
#
|
20
|
+
# Returns a column of sparse matrix by its position
|
21
|
+
def get_col(pos)
|
22
|
+
get_dimension({dimension: 1, position: 0}, pos)
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# @return [Array] The array that contains rows of matrix
|
27
|
+
# Returns sparse matrix in its regular view
|
28
|
+
def regular_view
|
29
|
+
Array.new(@n) { |i| get_row(i) }
|
30
|
+
end
|
31
|
+
|
32
|
+
##
|
33
|
+
# @param [SparseMatrix::Object] matrix - A matrix to multiply to
|
34
|
+
# @raise [ArgumentError] if count of columns of right matrix
|
35
|
+
# doesn't match count of rows of left matrix
|
36
|
+
#
|
37
|
+
# Returns a matrix in its regular view but multiplied by other matrix
|
38
|
+
def multiply(matrix)
|
39
|
+
raise 'wrong argument' if @n != matrix.m
|
40
|
+
|
41
|
+
rows = regular_view
|
42
|
+
result = Array.new(@n) { Array.new }
|
43
|
+
(0...@n).each { |i|
|
44
|
+
(0...matrix.m).each { |j|
|
45
|
+
result[i] << matrix
|
46
|
+
.get_col(j)
|
47
|
+
.zip(rows[i])
|
48
|
+
.inject(0) { |acc, current| acc + current[0] * current[1] }
|
49
|
+
}
|
50
|
+
}
|
51
|
+
result
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# @param [Integer] num - A number to multiply to
|
56
|
+
#
|
57
|
+
# Multiplies matrix by a number
|
58
|
+
def mult_by_num(num)
|
59
|
+
return SparseMatrix.new(@n, @m) if num.zero?
|
60
|
+
|
61
|
+
res = copy
|
62
|
+
res.triplets.each do |triplet|
|
63
|
+
triplet[2] *= num
|
64
|
+
end
|
65
|
+
res
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def get_dimension(selector, pos)
|
71
|
+
raise 'wrong argument' if pos.negative? || pos > @m
|
72
|
+
|
73
|
+
result = Array.new(@m, 0)
|
74
|
+
@triplets
|
75
|
+
.select { |triplet| triplet[selector[:dimension]] == pos }
|
76
|
+
.each { |triplet| result[triplet[selector[:position]]] = triplet[2] }
|
77
|
+
result
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
module Silicium
|
2
|
+
require_relative 'sugar'
|
3
|
+
require_relative 'conversions'
|
4
|
+
require_relative 'trans'
|
5
|
+
require_relative 'adding'
|
6
|
+
require_relative 'multi'
|
7
|
+
|
8
|
+
# here goes the sparse module
|
9
|
+
module Sparse
|
10
|
+
# here goes the Sparse class
|
11
|
+
class SparseMatrix
|
12
|
+
attr_reader :triplets
|
13
|
+
attr_reader :n
|
14
|
+
attr_reader :m
|
15
|
+
##
|
16
|
+
# @param [Integer] rows - Count of rows
|
17
|
+
# @param [Integer] cols - Count of columns
|
18
|
+
#
|
19
|
+
# Initialize matrix with count of rows and columns
|
20
|
+
def initialize(rows, cols)
|
21
|
+
@n = rows
|
22
|
+
@m = cols
|
23
|
+
@triplets = []
|
24
|
+
end
|
25
|
+
|
26
|
+
##
|
27
|
+
# @return [SparseMatrix::Object] - Returns a copy of a SparseMatrix object
|
28
|
+
#
|
29
|
+
# Creates a copy of matrix object
|
30
|
+
def copy
|
31
|
+
new = SparseMatrix.new(@n, @m)
|
32
|
+
triplets.each do |triplet|
|
33
|
+
new.add(triplet[0], triplet[1], triplet[2])
|
34
|
+
end
|
35
|
+
new
|
36
|
+
end
|
37
|
+
|
38
|
+
##
|
39
|
+
# @param [Integer] i_pos - The i position of an element
|
40
|
+
# @param [Integer] j_pos - The j position of an element
|
41
|
+
# @param [Integer] elem - The value of an element to be added
|
42
|
+
#
|
43
|
+
# Adds an element to matrix by its position and value
|
44
|
+
def add(i_pos, j_pos, elem)
|
45
|
+
if i_pos > @n || j_pos > @m || i_pos.negative? || j_pos.negative?
|
46
|
+
raise 'out of range'
|
47
|
+
end
|
48
|
+
|
49
|
+
f = false
|
50
|
+
@triplets.each do |item|
|
51
|
+
if item[0] == i_pos && item[1] == j_pos
|
52
|
+
item = [i_pos, j_pos, elem]
|
53
|
+
f = true
|
54
|
+
break
|
55
|
+
end
|
56
|
+
end
|
57
|
+
@triplets.push([i_pos, j_pos, elem]) unless f
|
58
|
+
end
|
59
|
+
|
60
|
+
##
|
61
|
+
# @param [Integer] i_pos - The i position of an element
|
62
|
+
# @param [Integer] j_pos - The j position of an element
|
63
|
+
# @return [Integer] The element on i,j position
|
64
|
+
#
|
65
|
+
# Returns an element by its position
|
66
|
+
def get(i_pos, j_pos)
|
67
|
+
triplets.each do |triplet|
|
68
|
+
if triplet[0] == i_pos && triplet[1] == j_pos
|
69
|
+
return triplet[2]
|
70
|
+
end
|
71
|
+
end
|
72
|
+
0
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Silicium
|
2
|
+
module Sparse
|
3
|
+
# addition for SparseMatrix class
|
4
|
+
class SparseMatrix
|
5
|
+
##
|
6
|
+
# @param [SparseMatrix] other - second matrix for adding
|
7
|
+
# @raise [ArgumentError] If the size of the first matrix doesn't match the size of the second matrix
|
8
|
+
# @return [SparseMatrix] Matrix as the sum of the other two matrices
|
9
|
+
#
|
10
|
+
# Makes the sum of two matrix
|
11
|
+
def +(other)
|
12
|
+
adding(other)
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
# @param [SparseMatrix] other - second matrix for adding
|
17
|
+
# @raise [ArgumentError] If the size of the first matrix doesn't match the size of the second matrix
|
18
|
+
# @return [SparseMatrix] Matrix as the sum of the other two matrices
|
19
|
+
#
|
20
|
+
# Makes the sum of two matrix
|
21
|
+
def -(other)
|
22
|
+
adding(other.mult_by_num(-1))
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# @param [SparseMatrix::Object] other - A matrix to multiply to
|
27
|
+
# @raise [ArgumentError] if count of columns of right matrix
|
28
|
+
# doesn't match count of rows of left matrix
|
29
|
+
#
|
30
|
+
# Returns a matrix in its regular view but multiplied by other matrix
|
31
|
+
def *(other)
|
32
|
+
multiply(other)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|