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