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