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
data/lib/plotter.rb CHANGED
@@ -1,96 +1,256 @@
1
- require 'silicium'
2
- require 'chunky_png'
3
-
4
- module Silicium
5
- module Plotter
6
- ##
7
- # Factory method to return a color value, based on the arguments given.
8
- #
9
- # @overload Color(r, g, b, a)
10
- # @param (see ChunkyPNG::Color.rgba)
11
- # @return [Integer] The rgba color value.
12
- #
13
- # @overload Color(r, g, b)
14
- # @param (see ChunkyPNG::Color.rgb)
15
- # @return [Integer] The rgb color value.
16
- #
17
- # @overload Color(hex_value, opacity = nil)
18
- # @param (see ChunkyPNG::Color.from_hex)
19
- # @return [Integer] The hex color value, with the opacity applied if one
20
- # was given.
21
- #
22
- # @overload Color(color_name, opacity = nil)
23
- # @param (see ChunkyPNG::Color.html_color)
24
- # @return [Integer] The hex color value, with the opacity applied if one
25
- # was given.
26
- #
27
- # @overload Color(color_value, opacity = nil)
28
- # @param [Integer, :to_i] The color value.
29
- # @return [Integer] The color value, with the opacity applied if one was
30
- # given.
31
- #
32
- # @return [Integer] The determined color value as RGBA integer.
33
- # @raise [ArgumentError] if the arguments weren't understood as a color.
34
- def color(*args)
35
- case args.length
36
- when 1; ChunkyPNG::Color.parse(args.first)
37
- when 2; (ChunkyPNG::Color.parse(args.first) & 0xffffff00) | args[1].to_i
38
- when 3; ChunkyPNG::Color.rgb(*args)
39
- when 4; ChunkyPNG::Color.rgba(*args)
40
- else raise ArgumentError, "Don't know how to create a color from #{args.inspect}!"
41
- end
42
- end
43
- ##
44
- # A class representing canvas for plotting bar charts and function graphs
45
- class Image
46
- ##
47
- # Creates a new plot with chosen +width+ and +height+ parameters
48
- # with background colored +bg_color+
49
- def initialize(width, height, bg_color = ChunkyPNG::Color::TRANSPARENT)
50
- @image = ChunkyPNG::Image.new(width, height, bg_color)
51
- end
52
-
53
- def rectangle(x, y, width, height, color)
54
- x_end = x + width - 1
55
- y_end = y + height - 1
56
- (x..x_end).each do |i|
57
- (y..y_end).each do |j|
58
- @image[i, j] = color
59
- end
60
- end
61
- end
62
-
63
- ##
64
- # Draws a bar chart in the plot using provided +bars+,
65
- # each of them has width of +bar_width+ and colored +bars_color+
66
- def bar_chart(bars, bar_width, bars_color = ChunkyPNG::Color('red @ 1.0'), axis_color = ChunkyPNG::Color::BLACK)
67
- if bars.count * bar_width > @image.width
68
- raise ArgumentError, 'Not enough big size of image to plot these number of bars'
69
- end
70
-
71
- padding = 5
72
- # Values of x and y on borders of plot
73
- minx = [bars.collect { |k, _| k }.min, 0].min
74
- maxx = [bars.collect { |k, _| k }.max, 0].max
75
- miny = [bars.collect { |_, v| v }.min, 0].min
76
- maxy = [bars.collect { |_, v| v }.max, 0].max
77
- dpux = Float((@image.width - 2 * padding)) / (maxx - minx + bar_width) # Dots per unit for X
78
- dpuy = Float((@image.height - 2 * padding)) / (maxy - miny) # Dots per unit for Y
79
- rectangle(padding, @image.height - padding - (miny.abs * dpuy).ceil, @image.width - 2 * padding, 1, axis_color) # Axis OX
80
- rectangle(padding + (minx.abs * dpux).ceil, padding, 1, @image.height - 2 * padding, axis_color) # Axis OY
81
-
82
- bars.each do |x, y| # Cycle drawing bars
83
- rectangle(padding + ((x + minx.abs) * dpux).floor,
84
- @image.height - padding - (([y, 0].max + miny.abs) * dpuy).ceil + (y.negative? ? 1 : 0),
85
- bar_width, (y.abs * dpuy).ceil, bars_color)
86
- end
87
- end
88
-
89
- ##
90
- # Exports plotted image to file +filename+
91
- def export(filename)
92
- @image.save(filename, :interlace => true)
93
- end
94
- end
95
- end
96
- end
1
+ require 'silicium'
2
+ require 'chunky_png'
3
+ require 'ruby2d'
4
+
5
+
6
+ module Silicium
7
+ ##
8
+ # Plotter module
9
+ # Module contains classes, that are different kinds of plain plotters
10
+ #
11
+ module Plotter
12
+ include Silicium::Geometry
13
+ # The Color module defines methods for handling colors. Within the Plotter
14
+ # library, the concepts of pixels and colors are both used, and they are
15
+ # both represented by a Integer.
16
+ #
17
+ # Pixels/colors are represented in RGBA components. Each of the four
18
+ # components is stored with a depth of 8 bits (maximum value = 255 =
19
+ # {Plotter::Color::MAX}). Together, these components are stored in a 4-byte
20
+ # Integer.
21
+ #
22
+ # A color will always be represented using these 4 components in memory.
23
+ # When the image is encoded, a more suitable representation can be used
24
+ # (e.g. rgb, grayscale, palette-based), for which several conversion methods
25
+ # are provided in this module.
26
+ module Color
27
+ extend ChunkyPNG::Color
28
+ include ChunkyPNG::Color
29
+ end
30
+ ##
31
+ # Factory method to return a color value, based on the arguments given.
32
+ #
33
+ # @overload Color(r, g, b, a)
34
+ # @param (see ChunkyPNG::Color.rgba)
35
+ # @return [Integer] The rgba color value.
36
+ #
37
+ # @overload Color(r, g, b)
38
+ # @param (see ChunkyPNG::Color.rgb)
39
+ # @return [Integer] The rgb color value.
40
+ #
41
+ # @overload Color(hex_value, opacity = nil)
42
+ # @param (see ChunkyPNG::Color.from_hex)
43
+ # @return [Integer] The hex color value, with the opacity applied if one
44
+ # was given.
45
+ #
46
+ # @overload Color(color_name, opacity = nil)
47
+ # @param (see ChunkyPNG::Color.html_color)
48
+ # @return [Integer] The hex color value, with the opacity applied if one
49
+ # was given.
50
+ #
51
+ # @overload Color(color_value, opacity = nil)
52
+ # @param [Integer, :to_i] The color value.
53
+ # @return [Integer] The color value, with the opacity applied if one was
54
+ # given.
55
+ #
56
+ # @return [Integer] The determined color value as RGBA integer.
57
+ # @raise [ArgumentError] if the arguments weren't understood as a color.
58
+ def color(*args)
59
+ case args.length
60
+ when 1 then Color.parse(args.first)
61
+ when 2 then (Color.parse(args.first) & 0xffffff00) | args[1].to_i
62
+ when 3 then Color.rgb(*args)
63
+ when 4 then Color.rgba(*args)
64
+ else raise ArgumentError,
65
+ "Don't know how to create a color from #{args.inspect}!"
66
+ end
67
+ end
68
+ ##
69
+ # A class representing canvas for plotting bar charts and function graphs
70
+ class Image
71
+ include Silicium::Geometry
72
+ ##
73
+ # Creates a new plot with chosen +width+ and +height+ parameters
74
+ # with background colored +bg_color+
75
+ def initialize(width, height, bg_color = Color::TRANSPARENT, padding = 5)
76
+ @image = ChunkyPNG::Image.new(width, height, bg_color)
77
+ @padding = padding
78
+ end
79
+
80
+ def rectangle(left_upper, width, height, color)
81
+ x_end = left_upper.x + width - 1
82
+ y_end = left_upper.y + height - 1
83
+ (left_upper.x..x_end).each do |i|
84
+ (left_upper.y..y_end).each { |j| @image[i, j] = color }
85
+ end
86
+ end
87
+
88
+ private
89
+
90
+ def draw_axis(min, dpu, axis_color)
91
+ # Axis OX
92
+ rectangle(Point.new(
93
+ @padding,
94
+ @image.height - @padding - (min.y.abs * dpu.y).ceil
95
+ ),
96
+ @image.width - 2 * @padding,
97
+ 1,
98
+ axis_color)
99
+ # Axis OY
100
+ rectangle(Point.new(@padding + (min.x.abs * dpu.x).ceil, @padding),
101
+ 1, @image.height - 2 * @padding, axis_color)
102
+ end
103
+
104
+ public
105
+
106
+ ##
107
+ # Draws a bar chart in the plot using provided +bars+,
108
+ # each of them has width of +bar_width+ and colored +bars_color+
109
+ def bar_chart(bars, bar_width,
110
+ bars_color = Color('red @ 1.0'),
111
+ axis_color = Color::BLACK)
112
+ if bars.count * bar_width > @image.width
113
+ raise ArgumentError,
114
+ 'Not enough big size of image to plot these number of bars'
115
+ end
116
+
117
+ # Values of x and y on borders of plot
118
+ min = Point.new([bars.collect { |k, _| k }.min, 0].min,
119
+ [bars.collect { |_, v| v }.min, 0].min)
120
+ max = Point.new([bars.collect { |k, _| k }.max, 0].max,
121
+ [bars.collect { |_, v| v }.max, 0].max)
122
+
123
+ # Dots per unit
124
+ dpu = Point.new(
125
+ (@image.width - 2 * @padding).to_f / (max.x - min.x + bar_width),
126
+ (@image.height - 2 * @padding).to_f / (max.y - min.y)
127
+ )
128
+
129
+ draw_axis(min, dpu, axis_color)
130
+
131
+ bars.each do |x, y| # Cycle drawing bars
132
+ l_up_x = @padding + ((x + min.x.abs) * dpu.x).floor
133
+ l_up_y = if y.negative?
134
+ @image.height - @padding - (min.y.abs * dpu.y).ceil + 1
135
+ else
136
+ @image.height - @padding - ((y + min.y.abs) * dpu.y).ceil
137
+ end
138
+ rectangle(Point.new(l_up_x, l_up_y),
139
+ bar_width, (y.abs * dpu.y).ceil,
140
+ bars_color)
141
+ end
142
+ end
143
+
144
+ ##
145
+ # Exports plotted image to file +filename+
146
+ def export(filename)
147
+ @image.save(filename, interlace: true)
148
+ end
149
+ end
150
+
151
+ CENTER_X = Window.width / 2
152
+ CENTER_Y = Window.height / 2
153
+
154
+ mul = 100/1
155
+
156
+ ##
157
+ # draws axes
158
+ def draw_axes
159
+ Line.new(x1: 0, y1: CENTER_Y, x2: (get :width), y2: CENTER_Y, width: 1, color: 'white', z: 20)
160
+ Line.new(x1: CENTER_X, y1: 0, x2: CENTER_X, y2: (get :height), width: 1, color: 'white', z: 20)
161
+
162
+ x1 = CENTER_X
163
+ x2 = CENTER_X
164
+ while (x1 < Window.width * 1.1) and (x2 > Window.width * -1.1) do
165
+ Line.new(x1: x1, y1: CENTER_Y - 4, x2: x1, y2: CENTER_Y + 3, width: 1, color: 'white', z: 20)
166
+ Line.new(x1: x2, y1: CENTER_Y - 4, x2: x2, y2: CENTER_Y + 3, width: 1, color: 'white', z: 20)
167
+ x1 += mul
168
+ x2 -= mul
169
+ end
170
+
171
+ y1 = CENTER_Y
172
+ y2 = CENTER_Y
173
+ while (y1 < Window.height * 1.1) and (y2 > Window.height * -1.1) do
174
+ Line.new(x1: CENTER_X - 3, y1: y1, x2: CENTER_X + 3, y2: y1, width: 1, color: 'white', z: 20)
175
+ Line.new(x1: CENTER_X - 3, y1: y2, x2: CENTER_X + 3, y2: y2, width: 1, color: 'white', z: 20)
176
+ y1 += mul
177
+ y2 -= mul
178
+ end
179
+ end
180
+
181
+ ##
182
+ # Changes the coordinates to draw the next pixel for the +f+ function
183
+ # +x+ - current argument. +st+ - step to next point
184
+ def reset_step(x, st, &f)
185
+ y1 = f.call(x)
186
+ y2 = f.call(x + st)
187
+
188
+ if (y1 - y2).abs / mul > 1.0
189
+ [st / (y1 - y2).abs / mul, 0.001].max
190
+ else
191
+ st / mul * 2
192
+ end
193
+ end
194
+
195
+ ##
196
+ # Draws a point on coordinates +x+ and +y+
197
+ # with the scale +mul+ and color +col+
198
+ def draw_point(x, y, mul, col)
199
+ Line.new(
200
+ x1: CENTER_X + x * mul, y1: CENTER_Y - y * mul,
201
+ x2: CENTER_X + 1 + x * mul, y2: CENTER_Y + 2 - y * mul,
202
+ width: 1,
203
+ color: col,
204
+ z: 20
205
+ )
206
+ end
207
+
208
+ ##
209
+ # Reduces the interval to the window range. +a+ and +b+ that determine interval
210
+ def reduce_interval(a, b)
211
+ a *= mul
212
+ b *= mul
213
+ return [a, -(get :width) * 1.1].max / mul, [b, (get :width) * 1.1].min / mul
214
+ end
215
+
216
+ ##
217
+ # Draws the function +func+ at the interval from +a+ to +b+
218
+ def draw_fn(a, b, &func)
219
+ draw_axes
220
+
221
+ a, b = reduce_interval(a, b)
222
+
223
+ step = 0.38
224
+ c_step = step
225
+ arg = a
226
+
227
+ while arg < b do
228
+ c_step = step
229
+ begin
230
+ c_step = reset_step(arg, step) {|xx| fn(xx)}
231
+ rescue Math::DomainError
232
+ arg += c_step * 0.1
233
+ else
234
+ draw_point(arg, func.call(arg), mul, 'lime')
235
+ ensure
236
+ arg += c_step
237
+ end
238
+ end
239
+ end
240
+
241
+ ##
242
+ # show plot
243
+ def show_window
244
+ show
245
+ end
246
+
247
+ # @param [Integer] sc
248
+ def set_scale(sc)
249
+ mul = sc
250
+ end
251
+
252
+ end
253
+ end
254
+
255
+
256
+
@@ -0,0 +1,132 @@
1
+ module Silicium
2
+
3
+
4
+ module Algebra
5
+ ##
6
+ # TODO: class docs
7
+ class PolynomialDivision
8
+
9
+ DELTA = 0.01
10
+
11
+ # This function returns an array of coefficients obtained by parsing input string in format: "<coeff>*x**<degree>+..."
12
+ # Even if in your expression don't exist x with some degree, you should to write it with 0 coefficient
13
+ # Also free term you should to write with 0 degree
14
+ # Example: "2*x**5-3*x**4+0*x**3+0*x**2-5*x**1-6*x**0"
15
+ def polynom_parser(str)
16
+ copy_str = str.clone
17
+ sgn_array = [] # Array of signs
18
+ if copy_str[0] != '-'
19
+ sgn_array.push('+')
20
+ else
21
+ sgn_array.push('-')
22
+ copy_str[0] = ''
23
+ end
24
+ token = copy_str.split(/[-+]/)
25
+ (0..copy_str.size-1).each do |i|
26
+ sgn_array.push(copy_str[i]) if copy_str[i] == '-' || copy_str[i] == '+'
27
+ end
28
+ size = token.size - 1
29
+ coeff = [] # Array of coefficients
30
+ (0..size).each do |i|
31
+ degree = token[i].split('*') # Split by '*' to get coefficient and degree
32
+ degree[0] == 'x' ? coeff[i] = 1.0 : coeff[i] = degree[0].to_f
33
+ coeff[i] *= -1 if sgn_array[i] == '-'
34
+ end
35
+ coeff
36
+ end
37
+
38
+ # String implementation of result
39
+ def str_res_impl(coeff_res, sgn_array)
40
+ res_size = coeff_res.size
41
+ res_exp = ""
42
+ (0..res_size-1).each do |i|
43
+ res_exp += ((coeff_res[i].ceil(3)).to_s+"*x**"+(res_size - i - 1).to_s)
44
+ res_exp += sgn_array[i+1] if sgn_array[i+1] != '-'
45
+ end
46
+ res_exp
47
+ end
48
+
49
+ # String implementation of remained part
50
+ def str_rem_impl(coeff_1)
51
+ c = coeff_1.size
52
+ rem_exp = ""
53
+ (0..c-1).each do |i|
54
+ rem_exp += '+' if coeff_1[i] >= 0.0
55
+ rem_exp += ((coeff_1[i].ceil(3)).to_s+"*x**"+(c - i - 1).to_s)
56
+ end
57
+ rem_exp[0] = '' if rem_exp[0] == '+'
58
+ rem_exp
59
+ end
60
+
61
+ # This function returns array of 2 strings: first is the result of division polynom poly_1 on polynom poly_2
62
+ # Second - remainder
63
+ def polynom_division(poly_1, poly_2)
64
+ coeff_1 = polynom_parser(poly_1)
65
+ coeff_2 = polynom_parser(poly_2)
66
+ res_size = coeff_1.size - coeff_2.size + 1
67
+ coeff_result = Array.new(res_size)
68
+ sgn_array = Array.new(res_size + 1,'')
69
+ (0..res_size-1).each do |i|
70
+ cur_coeff = coeff_1[i] / coeff_2[0]
71
+ coeff_result[i] = cur_coeff
72
+ coeff_result[i] < 0 ? sgn_array[i] = '-' : sgn_array[i] = '+'
73
+ (0..coeff_2.size-1).each do |j|
74
+ coeff_1[i+j] -= coeff_2[j]*cur_coeff
75
+ end
76
+ end
77
+ res_exp = str_res_impl(coeff_result, sgn_array)
78
+ rem_exp = str_rem_impl(coeff_1[coeff_result.size..coeff_1.size-1])
79
+ [res_exp, rem_exp]
80
+ end
81
+
82
+ def compare_polynoms(poly1, poly2)
83
+ polynom_parser(poly1).size - polynom_parser(poly2).size
84
+ end
85
+
86
+ def zero_coeffs?(polynom, delta = DELTA)
87
+ polynom_parser(polynom).all?{ |item| item.abs < delta }
88
+ end
89
+
90
+ def round_coeffs(coefficients, delta = DELTA)
91
+ coefficients.map do |element|
92
+ (element.round - element).abs < delta ? element.round.to_f : element
93
+ end
94
+ end
95
+
96
+ def build_polynom_from_coeffs(coefficients)
97
+ "#{coefficients[0]}*x**#{coefficients.size - 1}" +
98
+ coefficients[1..-1].each_with_index.inject('') do |acc, (coefficient, index)|
99
+ leading_sign = coefficient >= 0 ? '+' : ''
100
+ acc + "#{leading_sign}#{coefficient}*x**#{ coefficients.size - index - 2 }"
101
+ end
102
+ end
103
+
104
+ # This function returns a string: greatest common integer divisor of two polynoms
105
+ def polynom_gcd(poly1, poly2, delta = DELTA)
106
+ divisor, remainder = order_gcd_operands(poly1, poly2)
107
+ until zero_coeffs?(remainder) do
108
+ division = polynom_division(divisor, remainder)
109
+ divisor = remainder
110
+ remainder = division[1]
111
+ end
112
+ normalizer = polynom_parser(divisor)[0]
113
+ temp_result = polynom_division(divisor, normalizer.to_s+'*x**0')[0]
114
+ coefficients = round_coeffs(polynom_parser(temp_result), delta)
115
+ build_polynom_from_coeffs(coefficients)
116
+ end
117
+
118
+ private
119
+
120
+ def order_gcd_operands(poly1, poly2)
121
+ if compare_polynoms(poly1, poly2) >= 0
122
+ divisor = poly2
123
+ remainder = polynom_division(poly1, divisor)[1]
124
+ else
125
+ divisor = poly1
126
+ remainder = polynom_division(poly2, divisor)[1]
127
+ end
128
+ [divisor, remainder]
129
+ end
130
+ end
131
+ end
132
+ end