statistical 0.1.1 → 0.1.2

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