67 lines
1.5 KiB
Ruby
67 lines
1.5 KiB
Ruby
|
module Statistics
|
||
|
module Distribution
|
||
|
class Weibull
|
||
|
attr_accessor :shape, :scale # k and lambda
|
||
|
|
||
|
def initialize(k, lamb)
|
||
|
self.shape = k.to_f
|
||
|
self.scale = lamb.to_f
|
||
|
end
|
||
|
|
||
|
def cumulative_function(random_value)
|
||
|
return 0 if random_value < 0
|
||
|
|
||
|
1 - Math.exp(-((random_value/scale) ** shape))
|
||
|
end
|
||
|
|
||
|
def density_function(value)
|
||
|
return if shape <= 0 || scale <= 0
|
||
|
return 0 if value < 0
|
||
|
|
||
|
left = shape/scale
|
||
|
center = (value/scale)**(shape - 1)
|
||
|
right = Math.exp(-((value/scale)**shape))
|
||
|
|
||
|
left * center * right
|
||
|
end
|
||
|
|
||
|
def mean
|
||
|
scale * Math.gamma(1 + (1/shape))
|
||
|
end
|
||
|
|
||
|
def mode
|
||
|
return 0 if shape <= 1
|
||
|
|
||
|
scale * (((shape - 1)/shape) ** (1/shape))
|
||
|
end
|
||
|
|
||
|
def variance
|
||
|
left = Math.gamma(1 + (2/shape))
|
||
|
right = Math.gamma(1 + (1/shape)) ** 2
|
||
|
|
||
|
(scale ** 2) * (left - right)
|
||
|
end
|
||
|
|
||
|
# Using the inverse CDF function, also called quantile, we can calculate
|
||
|
# a random sample that follows a weibull distribution.
|
||
|
#
|
||
|
# Formula extracted from https://www.taygeta.com/random/weibull.html
|
||
|
def random(elements: 1, seed: Random.new_seed)
|
||
|
results = []
|
||
|
|
||
|
srand(seed)
|
||
|
|
||
|
elements.times do
|
||
|
results << ((-1/scale) * Math.log(1 - rand)) ** (1/shape)
|
||
|
end
|
||
|
|
||
|
if elements == 1
|
||
|
results.first
|
||
|
else
|
||
|
results
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|