silicium 0.0.15 → 0.0.20
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 +4 -0
- data/.gitignore +3 -1
- data/.travis.yml +12 -1
- data/Gemfile +4 -0
- data/Makefile +269 -0
- data/README.md +2 -0
- data/Rakefile +7 -0
- data/docs/Object.html +117 -0
- data/docs/README_md.html +142 -0
- data/docs/Silicium.html +101 -0
- data/docs/Silicium/Combinatorics.html +270 -0
- data/docs/Silicium/Dice.html +99 -0
- data/docs/Silicium/Dice/Polyhedron.html +315 -0
- data/docs/Silicium/Dice/PolyhedronSet.html +321 -0
- data/docs/Silicium/Error.html +106 -0
- data/docs/Silicium/Geometry.html +940 -0
- data/docs/Silicium/Geometry/Line2dCanon.html +243 -0
- data/docs/Silicium/Geometry/VariablesOrderException.html +106 -0
- data/docs/Silicium/Graphs.html +164 -0
- data/docs/Silicium/Graphs/GraphError.html +106 -0
- data/docs/Silicium/Graphs/OrientedGraph.html +775 -0
- data/docs/Silicium/Graphs/UnorientedGraph.html +284 -0
- data/docs/Silicium/IntegralDoesntExistError.html +106 -0
- data/docs/Silicium/NumericalIntegration.html +521 -0
- data/docs/Silicium/Optimization.html +639 -0
- data/docs/Silicium/Plotter.html +186 -0
- data/docs/Silicium/Plotter/Image.html +297 -0
- data/docs/created.rid +9 -0
- data/docs/css/fonts.css +167 -0
- data/docs/css/rdoc.css +619 -0
- data/docs/fonts/Lato-Light.ttf +0 -0
- data/docs/fonts/Lato-LightItalic.ttf +0 -0
- data/docs/fonts/Lato-Regular.ttf +0 -0
- data/docs/fonts/Lato-RegularItalic.ttf +0 -0
- data/docs/fonts/SourceCodePro-Bold.ttf +0 -0
- data/docs/fonts/SourceCodePro-Regular.ttf +0 -0
- data/docs/images/add.png +0 -0
- data/docs/images/arrow_up.png +0 -0
- data/docs/images/brick.png +0 -0
- data/docs/images/brick_link.png +0 -0
- data/docs/images/bug.png +0 -0
- data/docs/images/bullet_black.png +0 -0
- data/docs/images/bullet_toggle_minus.png +0 -0
- data/docs/images/bullet_toggle_plus.png +0 -0
- data/docs/images/date.png +0 -0
- data/docs/images/delete.png +0 -0
- data/docs/images/find.png +0 -0
- data/docs/images/loadingAnimation.gif +0 -0
- data/docs/images/macFFBgHack.png +0 -0
- data/docs/images/package.png +0 -0
- data/docs/images/page_green.png +0 -0
- data/docs/images/page_white_text.png +0 -0
- data/docs/images/page_white_width.png +0 -0
- data/docs/images/plugin.png +0 -0
- data/docs/images/ruby.png +0 -0
- data/docs/images/tag_blue.png +0 -0
- data/docs/images/tag_green.png +0 -0
- data/docs/images/transparent.png +0 -0
- data/docs/images/wrench.png +0 -0
- data/docs/images/wrench_orange.png +0 -0
- data/docs/images/zoom.png +0 -0
- data/docs/index.html +132 -0
- data/docs/js/darkfish.js +84 -0
- data/docs/js/navigation.js +105 -0
- data/docs/js/navigation.js.gz +0 -0
- data/docs/js/search.js +110 -0
- data/docs/js/search_index.js +1 -0
- data/docs/js/search_index.js.gz +0 -0
- data/docs/js/searcher.js +229 -0
- data/docs/js/searcher.js.gz +0 -0
- data/docs/table_of_contents.html +608 -0
- data/lib/geometry.rb +236 -0
- data/lib/graph.rb +164 -0
- data/lib/numerical_integration.rb +147 -0
- data/lib/optimization.rb +144 -0
- data/lib/plotter.rb +96 -0
- data/lib/silicium.rb +0 -1
- data/lib/silicium/version.rb +1 -1
- data/lib/theory_of_probability.rb +227 -0
- data/silicium.gemspec +4 -2
- metadata +90 -3
data/lib/optimization.rb
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
require "silicium"
|
2
|
+
require 'fast_matrix'
|
3
|
+
|
4
|
+
module Silicium
|
5
|
+
module Optimization
|
6
|
+
|
7
|
+
|
8
|
+
# reflector function
|
9
|
+
def re_lu(x)
|
10
|
+
x.negative? ? 0 : x
|
11
|
+
end
|
12
|
+
|
13
|
+
#sigmoid function
|
14
|
+
def sigmoid(x)
|
15
|
+
1.0 / (1 + Math.exp(-x))
|
16
|
+
end
|
17
|
+
|
18
|
+
#integrating using method Monte Carlo (f - function, a, b - integrating limits, n - amount of random numbers)
|
19
|
+
def integrating_Monte_Carlo_base(a, b, n = 100000, &block)
|
20
|
+
res = 0
|
21
|
+
range = a..b.to_f
|
22
|
+
for i in 1..(n + 1)
|
23
|
+
x = rand(range)
|
24
|
+
res += (b - a) * 1.0 / n * block.call(x)
|
25
|
+
end
|
26
|
+
res
|
27
|
+
end
|
28
|
+
|
29
|
+
#return true if array is sorted
|
30
|
+
def sorted?(a)
|
31
|
+
return false if a.nil?
|
32
|
+
for i in 0..a.length - 2
|
33
|
+
if (a[i + 1] < a[i])
|
34
|
+
return false
|
35
|
+
end
|
36
|
+
end
|
37
|
+
true
|
38
|
+
end
|
39
|
+
|
40
|
+
#fastest(but it is not exactly) sort, modify sequance
|
41
|
+
def bogosort!(a)
|
42
|
+
if (a.nil?)
|
43
|
+
raise ArgumentError, "Nil array in bogosort"
|
44
|
+
end
|
45
|
+
while (!sorted?(a))
|
46
|
+
a.shuffle!
|
47
|
+
end
|
48
|
+
a
|
49
|
+
end
|
50
|
+
|
51
|
+
#fastest(but it is not exactly) sort
|
52
|
+
def bogosort(a)
|
53
|
+
if (a.nil?)
|
54
|
+
raise ArgumentError, "Nil array in bogosort"
|
55
|
+
end
|
56
|
+
crutch = a
|
57
|
+
while (!sorted?(crutch))
|
58
|
+
crutch = a.shuffle
|
59
|
+
end
|
60
|
+
crutch
|
61
|
+
end
|
62
|
+
|
63
|
+
#calculate current accuracy in Hook - Jeeves method
|
64
|
+
def accuracy(step)
|
65
|
+
acc = 0
|
66
|
+
step.each { |a| acc += a * a }
|
67
|
+
Math.sqrt(acc)
|
68
|
+
end
|
69
|
+
|
70
|
+
#do one Hook - Jeeves step
|
71
|
+
def hook_jeeves_step(x, i, step, &block)
|
72
|
+
x[i] += step[i]
|
73
|
+
tmp1 = block.call(x)
|
74
|
+
x[i] = x[i] - 2 * step[i]
|
75
|
+
tmp2 = block.call(x)
|
76
|
+
if (tmp1 > tmp2)
|
77
|
+
cur_f = tmp2
|
78
|
+
else
|
79
|
+
x[i] = x[i] + step[i] * 2
|
80
|
+
cur_f = tmp1
|
81
|
+
end
|
82
|
+
[cur_f, x[i]]
|
83
|
+
end
|
84
|
+
|
85
|
+
#switch step if current func value > previous func value
|
86
|
+
def switch_step(cur_f, prev_f, step, i)
|
87
|
+
return step[i] / 2.0 if cur_f >= prev_f #you can switch 2.0 on something else
|
88
|
+
step[i]
|
89
|
+
end
|
90
|
+
#Hook - Jeeves method for find minimum point (x - array of start variables, step - step of one iteration, eps - allowable error, alfa - slowdown of step,
|
91
|
+
#block - function which takes array x, WAENING function doesn't control correctness of input
|
92
|
+
def hook_jeeves(x, step, eps = 0.1, &block)
|
93
|
+
prev_f = block.call(x)
|
94
|
+
acc = accuracy(step)
|
95
|
+
while (acc > eps)
|
96
|
+
for i in 0..x.length - 1
|
97
|
+
tmp = hook_jeeves_step(x, i, step, &block)
|
98
|
+
cur_f = tmp[0]
|
99
|
+
x[i] = tmp[1]
|
100
|
+
step[i] = switch_step(cur_f, prev_f, step, i)
|
101
|
+
prev_f = cur_f
|
102
|
+
end
|
103
|
+
acc = accuracy(step)
|
104
|
+
end
|
105
|
+
x
|
106
|
+
end
|
107
|
+
|
108
|
+
#find centr of interval
|
109
|
+
def middle(a, b)
|
110
|
+
(a + b) / 2.0
|
111
|
+
end
|
112
|
+
|
113
|
+
#do one half division step
|
114
|
+
def half_division_step(a, b, c, &block)
|
115
|
+
if (block.call(a) * block.call(c) < 0)
|
116
|
+
b = c
|
117
|
+
c = middle(a, c)
|
118
|
+
else
|
119
|
+
a = c
|
120
|
+
c = middle(b, c)
|
121
|
+
end
|
122
|
+
[a, b, c]
|
123
|
+
end
|
124
|
+
|
125
|
+
#find root in [a, b], if he exist, if number of iterations > iters -> error
|
126
|
+
def half_division(a, b, eps = 0.001, &block)
|
127
|
+
iters = 1000000
|
128
|
+
c = middle(a, b)
|
129
|
+
while ((block.call(c).abs) > eps)
|
130
|
+
tmp = half_division_step(a, b, c, &block)
|
131
|
+
a = tmp[0]
|
132
|
+
b = tmp[1]
|
133
|
+
c = tmp[2]
|
134
|
+
iters -= 1
|
135
|
+
if iters == 0
|
136
|
+
raise RuntimeError, "Root not found! Check does he exist, or change eps or iters"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
c
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
end
|
144
|
+
end
|
data/lib/plotter.rb
ADDED
@@ -0,0 +1,96 @@
|
|
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
|
data/lib/silicium.rb
CHANGED
data/lib/silicium/version.rb
CHANGED
@@ -0,0 +1,227 @@
|
|
1
|
+
require 'silicium'
|
2
|
+
require 'plotter'
|
3
|
+
require 'chunky_png'
|
4
|
+
|
5
|
+
include Silicium::Plotter
|
6
|
+
module Silicium
|
7
|
+
|
8
|
+
module Combinatorics
|
9
|
+
|
10
|
+
def factorial(n)
|
11
|
+
res = (1..n).inject(:*) || 1
|
12
|
+
res
|
13
|
+
end
|
14
|
+
|
15
|
+
##
|
16
|
+
#Factorial for counting 3 parameters in one run
|
17
|
+
def fact(n, k)
|
18
|
+
res = [1,1,1]
|
19
|
+
if n > 1
|
20
|
+
fact_n_greater_1(n, k, res)
|
21
|
+
end
|
22
|
+
res
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
#Function C(n,k)
|
27
|
+
def combination(n, k)
|
28
|
+
f = fact(n, k)
|
29
|
+
if n < k or k <= 0
|
30
|
+
-1
|
31
|
+
else
|
32
|
+
f[0] / (f[2] * f[1])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
##
|
37
|
+
#Function A(n,k)
|
38
|
+
def arrangement(n, k)
|
39
|
+
f = fact(n, k)
|
40
|
+
if n < k or k <= 0
|
41
|
+
-1
|
42
|
+
else
|
43
|
+
f[0] / f[1]
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def fact_n_greater_1(n,k, res)
|
50
|
+
c = 1
|
51
|
+
for i in 2..n
|
52
|
+
c *= i
|
53
|
+
determining_i([i, n, k, c], res)
|
54
|
+
end
|
55
|
+
res[0] = c
|
56
|
+
end
|
57
|
+
|
58
|
+
def determining_i(arr, res)
|
59
|
+
if arr[0] == arr[1] - arr[2]
|
60
|
+
res[1] = arr[3]
|
61
|
+
end
|
62
|
+
if arr[0] == arr[2]
|
63
|
+
res[2] = arr[3]
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
module Dice
|
70
|
+
|
71
|
+
##
|
72
|
+
# Class represents a polyhedron
|
73
|
+
# csides - number or sides
|
74
|
+
# sides - array of sides(unusual for custom polyhedrons)
|
75
|
+
class Polyhedron
|
76
|
+
|
77
|
+
def csides
|
78
|
+
@csides
|
79
|
+
end
|
80
|
+
|
81
|
+
def sides
|
82
|
+
@sides
|
83
|
+
end
|
84
|
+
|
85
|
+
def to_s
|
86
|
+
sides
|
87
|
+
end
|
88
|
+
|
89
|
+
##
|
90
|
+
# initializing polyhedron's variables
|
91
|
+
# there are two ways how to create it
|
92
|
+
# 1: by number (6) - creates polyhedron with 6 sides [1,2,3,4,5,6]
|
93
|
+
# 2: by array ([1,3,5]) - creates polyhedron with 3 sides [1,3,5]
|
94
|
+
def initialize(sides)
|
95
|
+
@csides = 1
|
96
|
+
@sides = [1]
|
97
|
+
if sides.class == Integer and sides > 1
|
98
|
+
@csides = sides
|
99
|
+
(2..sides).each {|i| @sides << i}
|
100
|
+
elsif sides.class == Array and sides.size > 0
|
101
|
+
@csides = sides.size
|
102
|
+
@sides = sides.sort
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
##
|
107
|
+
# ability to throw a polyhedron
|
108
|
+
def throw
|
109
|
+
@sides[rand(0..@csides-1)]
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
##
|
114
|
+
# Class represents a PolyhedronsSet
|
115
|
+
# percentage - hash with chances of getting definite score
|
116
|
+
class PolyhedronSet
|
117
|
+
|
118
|
+
def initialize(arr)
|
119
|
+
@pons = parse_pons(arr).sort_by{|item| -item.csides}
|
120
|
+
@percentage = count_chance_sum
|
121
|
+
end
|
122
|
+
|
123
|
+
def percentage
|
124
|
+
@percentage
|
125
|
+
end
|
126
|
+
|
127
|
+
##
|
128
|
+
# returns array of polyhedrons
|
129
|
+
def to_s
|
130
|
+
res = @pons.map {|item| item.to_s}
|
131
|
+
res
|
132
|
+
end
|
133
|
+
|
134
|
+
##
|
135
|
+
# ability to throw a polyhedron's set using hash of chances
|
136
|
+
def throw
|
137
|
+
sum = 0
|
138
|
+
r = rand
|
139
|
+
@percentage.each do |item|
|
140
|
+
sum += item[1]
|
141
|
+
if sum > r
|
142
|
+
item[0]
|
143
|
+
break
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
##
|
149
|
+
# creating a graph representing chances of getting points
|
150
|
+
def make_graph_by_plotter(x = percentage.size * 10, y = percentage.size * 10)
|
151
|
+
filename = 'tmp/percentage.png'
|
152
|
+
File.delete(filename) if File.exist?(filename)
|
153
|
+
plotter = Image.new(x, y)
|
154
|
+
plotter.bar_chart(percentage, 1, color('red @ 1.0'))
|
155
|
+
plotter.export(filename)
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
|
160
|
+
def parse_pons(arr)
|
161
|
+
res = []
|
162
|
+
arr.each do |item|
|
163
|
+
res << Polyhedron.new(item)
|
164
|
+
end
|
165
|
+
res
|
166
|
+
end
|
167
|
+
|
168
|
+
def count_chance_sum_chances_step(arr1, arr2, arr3, h)
|
169
|
+
n = 0
|
170
|
+
m = 0
|
171
|
+
sum = 0
|
172
|
+
q = Queue.new
|
173
|
+
h1 = Hash.new
|
174
|
+
while m < arr2.size
|
175
|
+
sum = m_0([sum, n, m], q, h, arr1)
|
176
|
+
if q.size > arr2.size or m > 0
|
177
|
+
sum -= q.pop
|
178
|
+
end
|
179
|
+
h1[arr1[n] + arr2[m]] = sum
|
180
|
+
arr3 << (arr1[n] + arr2[m])
|
181
|
+
nmarr = n_less_arr1_size(n, arr1, m)
|
182
|
+
n, m = nmarr[0], nmarr[1]
|
183
|
+
end
|
184
|
+
h1
|
185
|
+
end
|
186
|
+
|
187
|
+
def m_0(arr, q, h, arr1)
|
188
|
+
if arr[2] == 0
|
189
|
+
a = h[arr1[arr[1]]]
|
190
|
+
q << a
|
191
|
+
arr[0] += a
|
192
|
+
end
|
193
|
+
arr[0]
|
194
|
+
end
|
195
|
+
|
196
|
+
def n_less_arr1_size(n, arr1, m)
|
197
|
+
if n < arr1.size - 1
|
198
|
+
n += 1
|
199
|
+
else
|
200
|
+
m += 1
|
201
|
+
end
|
202
|
+
[n,m]
|
203
|
+
end
|
204
|
+
|
205
|
+
def count_chance_sum
|
206
|
+
h = Hash.new
|
207
|
+
@pons[0].sides.each do |item|
|
208
|
+
h[item] = 1
|
209
|
+
end
|
210
|
+
arr3 = @pons[0].sides
|
211
|
+
for i in 1..@pons.size - 1
|
212
|
+
arr1 = arr3
|
213
|
+
arr3 = Array.new
|
214
|
+
arr2 = @pons[i].sides
|
215
|
+
h1 = count_chance_sum_chances_step(arr1, arr2, arr3, h)
|
216
|
+
h = h1
|
217
|
+
h1 = Hash.new
|
218
|
+
end
|
219
|
+
res = Hash.new
|
220
|
+
fchance = @pons.inject(1) { |mult, item| mult * item.csides }
|
221
|
+
arr3.each {|item| res[item] = Float(h[item]) / fchance}
|
222
|
+
res
|
223
|
+
end
|
224
|
+
|
225
|
+
end
|
226
|
+
end
|
227
|
+
end
|