silicium 0.0.20 → 0.0.21

Sign up to get free protection for your applications and to get access to all the features.
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