statistical 0.1.1 → 0.1.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 292baa7cd3d35aaa61324625eaaf0558e8436145
4
- data.tar.gz: 67d5997eb4a9d622e5467eed349dd448ff0fb4bd
3
+ metadata.gz: 4dbc8862a8de1c1bd3f982635434403c1664683e
4
+ data.tar.gz: a1a52cffbb67236dcb224fe72634d8eb1434a4d8
5
5
  SHA512:
6
- metadata.gz: 4fae7c95b560274b9251969e57ebe2559b8eb59fba27090accb5540b869ff9c8df5a4395008011efc7878cdb70ba24afe1a4a6224aac19d616f09603e072547a
7
- data.tar.gz: c52abd3464ed8511b6a76950f7c1d827453109e77f41073d2a1937d6d0b208b3f3d8f3fc40e8283ca64f9f7de038b92a98dd30553ce9c87ed4119c572b1710a8
6
+ metadata.gz: 70b321f214492e41ba6b0f18be837404d2ba8d6b3687b21345825865c0e6d0ceead63c9b905fca095ab68980add4e3ae15405437e2afcb8fb9bdbd81e97c4c2e
7
+ data.tar.gz: ea3e9138092628d5d1551ad0d2eb8a26d6c929001c3a84a1d949a5afa1750a8ac2a00041794317b9c294396cae6bd4d7e7497ef799722f7fcfc12235f33e5d66
data/.gitignore CHANGED
@@ -12,4 +12,6 @@
12
12
  /coverage/**
13
13
  *.so
14
14
  *.o
15
- .gitmsg
15
+ .gitmsg
16
+ /profile/**
17
+ spec/tmp/**
data/Gemfile CHANGED
@@ -1,6 +1,10 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- gem 'codeclimate-test-reporter', :group => :test, :require => nil
3
+ group :test do
4
+ gem 'codeclimate-test-reporter', require: nil
5
+ gem 'rspec-prof'
6
+ end
7
+
4
8
  gem 'yard', require: false
5
9
 
6
10
  # Other dependencies go in statistical.gemspec
data/Rakefile CHANGED
@@ -10,6 +10,7 @@ require 'statistical/version'
10
10
 
11
11
  RSpec::Core::RakeTask.new(:spec) do |t|
12
12
  t.verbose = false
13
+ t.rspec_opts = '-f p'
13
14
  end
14
15
 
15
16
  # Add a cop task for code linting
@@ -23,7 +24,7 @@ end
23
24
 
24
25
  # Build the gem
25
26
  task :build do
26
- system "gem build statistical.gemspec"
27
+ system 'gem build statistical.gemspec'
27
28
  end
28
29
 
29
30
  # Install gem locally
@@ -34,7 +35,7 @@ end
34
35
  # Release gem to github
35
36
  task :release => :build do
36
37
  system "git tag -a v#{Statistical::VERSION} -m 'Version #{Statistical::VERSION}'"
37
- system "git push --tags"
38
+ system 'git push --tags'
38
39
  system "gem push statistical-#{Statistical::VERSION}.gem"
39
40
  end
40
41
 
@@ -1,4 +1,4 @@
1
- require 'statistical/exceptions'
1
+ require 'statistical/helpers'
2
2
 
3
3
  module Statistical
4
4
  module Distribution
@@ -70,9 +70,7 @@ module Statistical
70
70
  # @return [Boolean] true if-and-only-if two instances are of the same
71
71
  # class and have the same parameters.
72
72
  def eql?(other)
73
- return false unless other.is_a?(self.class)
74
- # Compare parameters and other stuff here
75
- return true
73
+ return other.is_a?(self.class)
76
74
  end
77
75
 
78
76
  alias :== :eql?
@@ -1,14 +1,13 @@
1
- require 'statistical/exceptions'
2
1
  require 'statistical/distribution/<%= distribution%>'
3
2
 
4
3
  module Statistical
5
- # Companion RNG class for the continuous uniform distribution. Requires a
4
+ # Companion RNG class for the continuous <%= distribution.capitalize.camelcase %> distribution. Requires a
6
5
  # distrbution object of the corresponding distribution
7
6
  #
8
7
  # @author Vaibhav Yenamandra
9
8
  #
10
- # @attr_reader [Numeric] lower The lower bound of the uniform distribution.
11
- # @attr_reader [Numeric] upper The upper bound of the uniform distribution.
9
+ # @attr_reader [Numeric] lower The lower bound of the <%= distribution.capitalize.camelcase %> distribution.
10
+ # @attr_reader [Numeric] upper The upper bound of the <%= distribution.capitalize.camelcase %> distribution.
12
11
  module Rng
13
12
  class <%= distribution.capitalize.camelcase %>
14
13
  attr_reader :generator, # other params go here
@@ -18,15 +17,16 @@ module Statistical
18
17
  raise TypeError, "Expected Distribution object or nil, found #{dobj.class}"
19
18
  end
20
19
  dobj = Statistical::Distribution::<%= distribution.capitalize.camelcase %>.new if dobj.nil?
21
- @generator = Rng::Uniform.new(Distribution::Uniform.new, seed)
20
+ @generator = Random.new(seed)
22
21
  # Map other parameters here
23
22
  @sdist = dobj
24
23
  end
25
24
 
26
25
  # Return the next random number from the sequence
27
26
  #
28
- # @return next random number in the sequence
27
+ # @return [Float] next random number in the sequence
29
28
  def rand
29
+ @sdist.quantile(@generator.rand)
30
30
  end
31
31
 
32
32
  # Compare against another rng to see if they are the same
@@ -34,9 +34,8 @@ module Statistical
34
34
  # @return true if and only if, source distributions are the same and the
35
35
  # prng has the same initial state
36
36
  def eql?(other)
37
- return false unless other.is_a?(self.class)
38
- # Compare parameters and other stuff here
39
- @generator == other.generator
37
+ return other.is_a?(self.class) &&
38
+ @generator == other.generator
40
39
  end
41
40
 
42
41
  # Return the type of the source distribution
@@ -3,17 +3,11 @@ require 'statistical/rng/<%= distribution%>'
3
3
  require 'statistical/distribution/<%= distribution %>'
4
4
 
5
5
  describe Statistical::Rng::<%= distribution.capitalize.camelcase %> do
6
- it 'passes the G-test at a 95% significance level' do
7
- end
8
6
 
9
7
  describe '.new' do
10
- context 'when called with no arguments' do
11
- fail
12
- end
8
+ context 'when called with no arguments'
13
9
 
14
- context 'when parameters are specified' do
15
- fail
16
- end
10
+ context 'when parameters are specified'
17
11
 
18
12
  context 'when initialized with a seed' do
19
13
  it 'should be repeatable for the same arguments' do
@@ -23,17 +17,11 @@ describe Statistical::Rng::<%= distribution.capitalize.camelcase %> do
23
17
  end
24
18
 
25
19
  describe '#rand' do
26
- it 'returns a number between 0 and 1 by default' do
27
- fail
28
- end
29
-
30
- it 'returns a bounded value when bounds are specified' do
31
- fail
32
- end
20
+ it 'passes the G-test at a 95% significance level'
33
21
  end
34
22
 
35
23
  describe '#==' do
36
- context 'when compared against another uniform distribution' do
24
+ context 'when compared against another <%= distribution.capitalize.camelcase %> distribution' do
37
25
  it 'should return true if the bounds and seed are the same' do
38
26
  fail
39
27
  end
@@ -42,101 +30,70 @@ describe Statistical::Rng::<%= distribution.capitalize.camelcase %> do
42
30
  fail
43
31
  end
44
32
  end
45
-
46
- context 'when compared against any other distribution class' do
47
- it 'should return false if classes are different' do
48
- fail
49
- end
50
- end
51
33
  end
52
34
  end
53
35
 
54
36
 
55
37
  describe Statistical::Distribution::<%= distribution.capitalize.camelcase %> do
56
38
  describe '.new' do
57
- context 'when called with no arguments' do
58
- fail
59
- end
60
-
61
- context 'when upper and lower bounds are specified' do
62
- fail
63
- end
39
+ context 'when called with no arguments'
40
+
41
+ context 'when upper and lower bounds are specified'
64
42
  end
65
-
66
-
43
+
44
+
67
45
  describe '#pdf' do
68
- context 'when called with x < lower_bound' do
69
- fail
70
- end
71
-
72
- context 'when called with x > upper_bound' do
73
- fail
74
- end
75
-
76
- context 'when called with x in [lower_bound, upper_bound]' do
77
- fail
78
- end
46
+ context 'when called with x < lower_bound'
47
+
48
+ context 'when called with x > upper_bound'
49
+
50
+ context 'when called with x in [lower_bound, upper_bound]'
79
51
  end
80
-
52
+
81
53
  describe '#cdf' do
82
- context 'when called with x < lower' do
83
- fail
84
- end
85
-
86
- context 'when called with x > upper' do
87
- fail
88
- end
89
-
90
- context 'when called with x in [lower, upper]' do
91
- fail
92
- end
54
+ context 'when called with x < lower'
55
+
56
+ context 'when called with x > upper'
57
+
58
+ context 'when called with x in [lower, upper]'
93
59
  end
94
-
60
+
95
61
  describe '#quantile' do
96
- context 'when called for x > 1' do
97
- fail
98
- end
99
-
100
62
  context 'when called for x < 0' do
101
- fail
63
+ let(:<%= distribution[0] %>dist) {Statistical::Distribution::<%= distribution.capitalize.camelcase %>.new}
64
+ it {
65
+ expect {<%= distribution[0] %>dist.quantile(-Float::EPSILON)}.to raise_error(RangeError)
66
+ }
102
67
  end
103
-
68
+
69
+ context 'when called for x > 1' do
70
+ let(:<%= distribution[0] %>dist) {Statistical::Distribution::<%= distribution.capitalize.camelcase %>.new}
71
+ it {
72
+ expect {<%= distribution[0] %>dist.quantile(1 + Float::EPSILON)}.to raise_error(RangeError)
73
+ }
74
+ end
75
+
104
76
  context 'when called for x in [0, 1]' do
105
- fail
77
+ let(:<%= distribution[0] %>dist) {Statistical::Distribution::<%= distribution.capitalize.camelcase %>.new}
106
78
  end
107
79
  end
108
-
80
+
109
81
  describe '#p_value' do
110
- it 'should be the same as #quantile' do
111
- fail
112
- end
113
- end
114
-
82
+ it 'should be the same as #quantile'
83
+ end
84
+
115
85
  describe '#mean' do
116
- it 'should return the correct mean' do
117
- fail
118
- end
86
+ it 'should return the correct mean'
119
87
  end
120
-
88
+
121
89
  describe '#variance' do
122
- it 'should return the correct variance' do
123
- fail
124
- end
90
+ it 'should return the correct variance'
125
91
  end
126
-
92
+
127
93
  describe '#==' do
128
- context 'when compared against another Uniform distribution' do
129
- it 'returns `true` if they have the same parameters' do
130
- fail
131
- end
132
-
133
- it 'returns `false` if they have different parameters' do
134
- fail
135
- end
136
- end
137
-
138
- context 'when compared against any distribution type' do
139
- fail
94
+ context 'when compared against another <%= distribution.capitalize.camelcase %> distribution' do
95
+ it 'returns `true` if they have the same parameters'
96
+ it 'returns `false` if they have different parameters'
140
97
  end
141
98
  end
142
99
  end
@@ -1,7 +1,12 @@
1
1
  require 'statistical/version'
2
2
  require 'statistical/distribution'
3
3
  require 'statistical/rng'
4
- require 'core_extensions'
4
+ require 'statistical/core_extensions'
5
5
 
6
6
  module Statistical
7
+ using Statistical::StringExtensions
8
+ using Statistical::ArrayExtensions
9
+
10
+ # Truncated Euler-Mascheroni constant
11
+ EULER_GAMMA = 0.5772156649015328
7
12
  end
@@ -0,0 +1,44 @@
1
+ # All core class modifications go here
2
+ module Statistical
3
+ # Module to contain all String refinements
4
+ module StringExtensions
5
+ refine String do
6
+ # Convert CamelCase to snake_case
7
+ def snakecase
8
+ gsub(/::/, '/')
9
+ .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
10
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
11
+ .tr('-', '_')
12
+ .downcase
13
+ end
14
+
15
+ # convert snake_case to CamelCase
16
+ def camelcase
17
+ split('_').map(&:capitalize).join
18
+ end
19
+ end
20
+ end
21
+
22
+ # Module to contain all Array refinements
23
+ module ArrayExtensions
24
+ refine Array do
25
+ def sum
26
+ inject(:+)
27
+ end
28
+
29
+ def mean
30
+ sum.fdiv(count)
31
+ end
32
+
33
+ # Population variance
34
+ def pvariance
35
+ map { |x| (x - mean)**2}.sum.fdiv(count)
36
+ end
37
+
38
+ # Sample variance
39
+ def svariance
40
+ map { |x| (x - mean)**2}.sum.fdiv(count - 1)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -5,11 +5,15 @@ require 'statistical/distribution/bernoulli'
5
5
  require 'statistical/distribution/exponential'
6
6
  require 'statistical/distribution/laplace'
7
7
  require 'statistical/distribution/weibull'
8
+ require 'statistical/distribution/frechet'
9
+ require 'statistical/distribution/gumbel'
8
10
 
9
11
  module Statistical
10
12
  # Factory module used to create instances of various distributions classes
11
13
  # nested under itself
12
14
  module Distribution
15
+ using Statistical::StringExtensions
16
+
13
17
  # @private
14
18
  # No need to document this
15
19
  # Dynamically add constants when called
@@ -0,0 +1,125 @@
1
+ require 'statistical/helpers'
2
+
3
+ module Statistical
4
+ module Distribution
5
+ # This class models the Frechet (or inverse Weibull) distribution which is
6
+ # a type-2 extreme value distribution.
7
+ #
8
+ # @author Vaibhav Yenamandra
9
+ # @attr_reader [Numeric] alpha Mandatory shape parameter of the distribution
10
+ # @attr_reader [Numeric] location Optional location parameter
11
+ # @attr_reader [Numeric] scale Optional scale parameter
12
+ # @attr_reader [Numeric] support Support / domain of the distribution's
13
+ # PDF / CDF
14
+ class Frechet
15
+ attr_reader :alpha, :location, :scale, :support
16
+
17
+ # Returns a new `Statistical::Distribution::Frechet` instance
18
+ #
19
+ # @param [Numeric] alpha Mandatory shape parameter of the distribution
20
+ # @param [Numeric] location Optional location parameter
21
+ # @param [Numeric] scale Optional scale parameter
22
+ # @return [Frechet] `Statistical::Distribution::Frechet` instance
23
+ def initialize(alpha = nil, location = 0, scale = 1)
24
+ raise ArgumentError if alpha.nil?
25
+
26
+ @alpha = alpha.to_f
27
+ @location = location.to_f
28
+ @scale = scale.to_f
29
+ @support = Domain[@location, Float::INFINITY, :full_open]
30
+ end
31
+
32
+ # Returns value of probability density function at a point.
33
+ #
34
+ # @param [Numeric] x A real valued point
35
+ # @return [Float] Probability density function evaluated at `x`
36
+ def pdf(x)
37
+ xs = (x - @location) / @scale
38
+
39
+ # Not following the usual array lookup idiom here since the PDF
40
+ # expression is ill-defined (Complex) for x < location. Lazily evaluated
41
+ # expressions would help retain the array lookup idiom, but that's for
42
+ # later
43
+ if (@support <=> x).zero?
44
+ return (@alpha / @scale) * xs**(-1 - @alpha) * Math.exp(-(xs**-@alpha))
45
+ else
46
+ return 0
47
+ end
48
+ end
49
+
50
+ # Returns value of cumulative density function upto the specified point
51
+ #
52
+ # @param [Numeric] x A real valued point
53
+ # @return [Float] Cumulative density function evaluated for F(u <= x)
54
+ def cdf(x)
55
+ xs = (x - @location) / @scale
56
+
57
+ case @support <=> x
58
+ when 0
59
+ return Math.exp(-(xs**-@alpha))
60
+ when 1
61
+ return 1
62
+ when -1
63
+ return 0
64
+ end
65
+ end
66
+
67
+ # Returns value of inverse CDF for a given probability
68
+ #
69
+ # @see #p_value
70
+ #
71
+ # @param [Numeric] p a value within [0, 1]
72
+ # @return [Float] Inverse CDF for valid p
73
+ # @raise [RangeError] if p > 1 or p < 0
74
+ def quantile(p)
75
+ raise RangeError, "`p` must be in [0, 1], found: #{p}" if p < 0 || p > 1
76
+ return @location + @scale * ((-Math.log(p))**(-1 / @alpha))
77
+ end
78
+
79
+ # Returns the mean value for the calling instance. Calculated mean, and
80
+ # not inferred from simulations
81
+ #
82
+ # @return Mean of the distribution
83
+ def mean
84
+ return [
85
+ Float::INFINITY,
86
+ @location + @scale * Math.gamma(1 - 1 / @alpha),
87
+ Float::INFINITY
88
+ ][@alpha <=> 1.0]
89
+ end
90
+
91
+ # Returns the expected value of variance for the calling instance.
92
+ #
93
+ # @return Variance of the distribution
94
+ def variance
95
+ return [
96
+ Float::INFINITY,
97
+ @scale * @scale * (
98
+ Math.gamma(1 - 2 / @alpha) -
99
+ Math.gamma(1 - 1 / @alpha)**2
100
+ ),
101
+ Float::INFINITY
102
+ ][@alpha <=> 2.0]
103
+ end
104
+
105
+ # Compares two distribution instances and returns a boolean outcome
106
+ # Available publicly as #==
107
+ #
108
+ # @private
109
+ #
110
+ # @return [Boolean] true if-and-only-if two instances are of the same
111
+ # class and have the same parameters.
112
+ def eql?(other)
113
+ return other.is_a?(self.class) &&
114
+ @alpha == other.alpha &&
115
+ @location == other.location &&
116
+ @scale == other.scale
117
+ end
118
+
119
+ alias :== :eql?
120
+ alias :p_value :quantile
121
+
122
+ private :eql?
123
+ end
124
+ end
125
+ end
@@ -0,0 +1,98 @@
1
+ require 'statistical/helpers'
2
+
3
+ module Statistical
4
+ module Distribution
5
+ # Distribution class for Extreme value type-3 or Gumbel distribution
6
+ #
7
+ # @author Vaibhav Yenamandra
8
+ #
9
+ # @attr_reader location [Float] The distributions location parameter
10
+ # @attr_reader scale [Float] The dstribution's scale parameter
11
+ # @attr_reader support [Float] The region of the real line where this
12
+ # distribution is defined to exist
13
+ class Gumbel
14
+ attr_reader :location, :scale, :support
15
+
16
+ # Returns a new `Statistical::Distribution::Gumbel` instance
17
+ #
18
+ # @param [Types] location Description
19
+ # @return `Statistical::Distribution::Gumbel` instance
20
+ def initialize(location = 0, scale = 1)
21
+ @location = location.to_f
22
+ @scale = scale.to_f
23
+ @support = Domain[-Float::INFINITY, Float::INFINITY, :full_open]
24
+ end
25
+
26
+ # Returns value of probability density function at a point.
27
+ #
28
+ # @param [Numeric] x A real valued point
29
+ # @return Probability density function evaluated at `x`
30
+ def pdf(x)
31
+ xa = (x - @location) / @scale
32
+ return [
33
+ Math.exp(-xa - Math.exp(-xa)) / @scale,
34
+ 0.0,
35
+ 0.0
36
+ ][@support <=> x]
37
+ end
38
+
39
+ # Returns value of cumulative density function upto a point.
40
+ #
41
+ # @param [Numeric] x A real valued point
42
+ # @return Cumulative density function evaluated for F(u <= x)
43
+ def cdf(x)
44
+ xa = (x - @location) / @scale
45
+ return [
46
+ Math.exp(-Math.exp(-xa)),
47
+ 1.0,
48
+ 0.0
49
+ ][@support <=> x]
50
+ end
51
+
52
+ # Returns value of inverse CDF for a given probability
53
+ #
54
+ # @see #p_value
55
+ #
56
+ # @param [Numeric] p a value within [0, 1]
57
+ # @return Inverse CDF for valid p
58
+ # @raise [RangeError] if p > 1 or p < 0
59
+ def quantile(p)
60
+ raise RangeError, "`p` must be in [0, 1], found: #{p}" if p < 0 || p > 1
61
+ return @location - @scale * Math.log(-Math.log(p))
62
+ end
63
+
64
+ # Returns the expected value of the mean for the calling instance.
65
+ #
66
+ # @return Mean of the distribution
67
+ def mean
68
+ return @location + @scale * Statistical::EULER_GAMMA
69
+ end
70
+
71
+ # Returns the expected value of variance for the calling instance.
72
+ #
73
+ # @return Variance of the distribution
74
+ def variance
75
+ return ((Math::PI * @scale)**2) / 6
76
+ end
77
+
78
+ # Compares two distribution instances and returns a boolean outcome
79
+ # Available publicly as #==
80
+ #
81
+ # @private
82
+ #
83
+ # @param other A distribution object (preferred)
84
+ # @return [Boolean] true if-and-only-if two instances are of the same
85
+ # class and have the same parameters.
86
+ def eql?(other)
87
+ return other.is_a?(self.class) &&
88
+ @location == other.location &&
89
+ @scale == other.scale
90
+ end
91
+
92
+ alias :== :eql?
93
+ alias :p_value :quantile
94
+
95
+ private :eql?
96
+ end
97
+ end
98
+ end
@@ -43,8 +43,7 @@ module Statistical
43
43
  def cdf(x)
44
44
  return [0.5,
45
45
  1.0 - 0.5 * Math.exp((@location - x).fdiv(@scale)),
46
- 0.5 * Math.exp((x - @location).fdiv(@scale))
47
- ][x <=> @location]
46
+ 0.5 * Math.exp((x - @location).fdiv(@scale))][x <=> @location]
48
47
  end
49
48
 
50
49
  # Returns value of inverse CDF for a given probability
@@ -59,8 +58,7 @@ module Statistical
59
58
 
60
59
  return [@location,
61
60
  @location - @scale * Math.log(2 * (1.0 - p)),
62
- @scale * Math.log(2 * p) + @location
63
- ][p <=> 0.5]
61
+ @scale * Math.log(2 * p) + @location][p <=> 0.5]
64
62
  end
65
63
 
66
64
  # Returns the expected mean value for the calling instance.
@@ -1,3 +1,5 @@
1
+ require 'statistical/core_extensions'
2
+
1
3
  module Statistical
2
4
  # Module to collect all abstractions of distributions
3
5
  module Distribution
@@ -8,6 +10,8 @@ module Statistical
8
10
  # @attr_reader [Array, Numeric] support The support set of valid values a
9
11
  # random variate from the distribution can take. Must have at least 1 value
10
12
  class UniformDiscrete
13
+ using Statistical::ArrayExtensions
14
+
11
15
  attr_reader :count, :support, :lower, :upper
12
16
  # Returns a model for the discrete uniform distribution on all elements
13
17
  # present in the given set of elemets `elems`
@@ -108,7 +112,7 @@ module Statistical
108
112
  #
109
113
  # @return [Float] Variance of the distribution
110
114
  def variance
111
- return @support.variance
115
+ return @support.pvariance
112
116
  end
113
117
 
114
118
  # Compares two distribution instances and returns a boolean
@@ -33,8 +33,7 @@ module Statistical
33
33
  return [(@shape / @scale) * ((x / @scale)**(@shape - 1)) *
34
34
  Math.exp(-((x / @scale)**@shape)),
35
35
  0.0,
36
- 0.0
37
- ][@support <=> x]
36
+ 0.0][@support <=> x]
38
37
  end
39
38
 
40
39
  # Returns value of cumulative density function at a point. Calculated
@@ -45,8 +44,7 @@ module Statistical
45
44
  def cdf(x)
46
45
  return [1 - Math.exp(-((x / @scale)**@shape)),
47
46
  1.0,
48
- 0.0
49
- ][@support <=> x]
47
+ 0.0][@support <=> x]
50
48
  end
51
49
 
52
50
  # Returns value of inverse CDF for a given probability
@@ -83,9 +83,9 @@ module Statistical
83
83
  @exclusions.each do |e|
84
84
  case e
85
85
  when Fixnum, Bignum, Float
86
- has_val = has_val || (e == val)
86
+ has_val = (has_val || (e == val))
87
87
  when Range
88
- has_val ||= e.include?(val)
88
+ has_val = (has_val || e.include?(val))
89
89
  end
90
90
  end
91
91
  return has_val
@@ -5,11 +5,15 @@ require 'statistical/rng/bernoulli'
5
5
  require 'statistical/rng/exponential'
6
6
  require 'statistical/rng/laplace'
7
7
  require 'statistical/rng/weibull'
8
+ require 'statistical/rng/frechet'
9
+ require 'statistical/rng/gumbel'
8
10
 
9
11
  module Statistical
10
12
  # Factory module to create instances of the various classes
11
13
  # nested under itself
12
14
  module Rng
15
+ using Statistical::StringExtensions
16
+
13
17
  # @private
14
18
  # No need to document this
15
19
  # Dynamically add constants when called
@@ -0,0 +1,59 @@
1
+ require 'statistical/distribution/frechet'
2
+
3
+ module Statistical
4
+ # Companion RNG class for the continuous uniform distribution. Requires a
5
+ # distrbution object of the corresponding distribution
6
+ #
7
+ # @author Vaibhav Yenamandra
8
+ #
9
+ # @attr_reader [Numeric] lower The lower bound of the uniform distribution.
10
+ # @attr_reader [Numeric] upper The upper bound of the uniform distribution.
11
+ module Rng
12
+ class Frechet
13
+ attr_reader :generator, :alpha, :location, :scale
14
+
15
+ def initialize(dobj = nil, seed = Random.new_seed)
16
+ if dobj.nil?
17
+ raise ArgumentError, 'Need a alpha-parametrized Frechet object!'
18
+ elsif !dobj.is_a?(Statistical::Distribution::Frechet)
19
+ raise TypeError, "Expected Frechet Distribution found #{dobj.class}"
20
+ end
21
+
22
+ @generator = Random.new(seed)
23
+ @alpha = dobj.alpha
24
+ @location = dobj.location
25
+ @scale = dobj.scale
26
+ @sdist = dobj
27
+ end
28
+
29
+ # Return the next random number from the sequence
30
+ #
31
+ # @return [Float] next random number in the sequence
32
+ def rand
33
+ return @sdist.quantile(@generator.rand)
34
+ end
35
+
36
+ # Compare against another rng to see if they are the same
37
+ #
38
+ # @return true if and only if, source distributions are the same and the
39
+ # prng has the same initial state
40
+ def eql?(other)
41
+ return other.is_a?(self.class) &&
42
+ @generator == other.generator &&
43
+ @alpha == other.alpha &&
44
+ @location == other.location &&
45
+ @scale == other.scale
46
+ end
47
+
48
+ # Return the type of the source distribution
49
+ #
50
+ # @return source distribution's type
51
+ def type
52
+ @sdist.class
53
+ end
54
+
55
+ alias_method :==, :eql?
56
+ private :eql?
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,59 @@
1
+ require 'statistical/distribution/gumbel'
2
+
3
+ module Statistical
4
+ # Companion RNG class for the continuous Gumbel distribution. Requires a
5
+ # distrbution object of the corresponding distribution
6
+ #
7
+ # @author Vaibhav Yenamandra
8
+ #
9
+ # @attr_reader [Float] location The location parameter of the Gumbel
10
+ # distribution
11
+ # @attr_reader [Float] scale The scale parameter of the Gumbel distribution
12
+ # @attr_reader [Float] generator The underlying uniform variate source used
13
+ # to power `Gumbel#rand`
14
+ module Rng
15
+ class Gumbel
16
+ attr_reader :generator, :location, :scale
17
+
18
+ def initialize(dobj = nil, seed = Random.new_seed)
19
+ unless dobj.nil? || dobj.is_a?(Statistical::Distribution::Gumbel)
20
+ raise TypeError,
21
+ "Expected Distribution object or nil, found #{dobj.class}"
22
+ end
23
+ dobj = Statistical::Distribution::Gumbel.new if dobj.nil?
24
+ @generator = Random.new(seed)
25
+ @location = dobj.location
26
+ @scale = dobj.scale
27
+ @sdist = dobj
28
+ end
29
+
30
+ # Return the next random number from the sequence
31
+ #
32
+ # @return [Float] next random number in the sequence
33
+ def rand
34
+ @sdist.quantile(@generator.rand)
35
+ end
36
+
37
+ # Compare against another rng to see if they are the same
38
+ #
39
+ # @return true if and only if, source distributions are the same and the
40
+ # prng has the same initial state
41
+ def eql?(other)
42
+ return other.is_a?(self.class) &&
43
+ @generator == other.generator &&
44
+ @location == other.location &&
45
+ @scale == other.scale
46
+ end
47
+
48
+ # Return the type of the source distribution
49
+ #
50
+ # @return source distribution's type
51
+ def type
52
+ @sdist.class
53
+ end
54
+
55
+ alias_method :==, :eql?
56
+ private :eql?
57
+ end
58
+ end
59
+ end
@@ -1,3 +1,3 @@
1
1
  module Statistical
2
- VERSION = '0.1.1'.freeze
2
+ VERSION = '0.1.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: statistical
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vaibhav Yenamandra
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-06-16 00:00:00.000000000 Z
11
+ date: 2016-06-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -116,11 +116,13 @@ files:
116
116
  - data/template/distribution.erb
117
117
  - data/template/rng.erb
118
118
  - data/template/spec.erb
119
- - lib/core_extensions.rb
120
119
  - lib/statistical.rb
120
+ - lib/statistical/core_extensions.rb
121
121
  - lib/statistical/distribution.rb
122
122
  - lib/statistical/distribution/bernoulli.rb
123
123
  - lib/statistical/distribution/exponential.rb
124
+ - lib/statistical/distribution/frechet.rb
125
+ - lib/statistical/distribution/gumbel.rb
124
126
  - lib/statistical/distribution/laplace.rb
125
127
  - lib/statistical/distribution/two_point.rb
126
128
  - lib/statistical/distribution/uniform.rb
@@ -130,6 +132,8 @@ files:
130
132
  - lib/statistical/rng.rb
131
133
  - lib/statistical/rng/bernoulli.rb
132
134
  - lib/statistical/rng/exponential.rb
135
+ - lib/statistical/rng/frechet.rb
136
+ - lib/statistical/rng/gumbel.rb
133
137
  - lib/statistical/rng/laplace.rb
134
138
  - lib/statistical/rng/two_point.rb
135
139
  - lib/statistical/rng/uniform.rb
@@ -1,35 +0,0 @@
1
- # All core class modifications go here
2
- String.class_eval do
3
- # Convert CamelCase to snake_case
4
- def snakecase
5
- gsub(/::/, '/')
6
- .gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
7
- .gsub(/([a-z\d])([A-Z])/, '\1_\2')
8
- .tr('-', '_')
9
- .downcase
10
- end
11
-
12
- # convert snake_case to CamelCase
13
- def camelcase
14
- split('_').map(&:capitalize).join
15
- end
16
- end
17
-
18
- Array.class_eval do
19
- def sum
20
- inject(:+)
21
- end
22
-
23
- def mean
24
- sum.fdiv(count)
25
- end
26
-
27
- def variance
28
- map { |x| (x - mean)**2}.sum.fdiv(count)
29
- end
30
-
31
- def comprehend(&block)
32
- return self if block.nil?
33
- collect(&block).compact
34
- end
35
- end