bernoulli 0.3.1 → 0.4

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.
data/Gemfile CHANGED
@@ -1,4 +1,2 @@
1
1
  source :rubygems
2
-
3
2
  gemspec
4
-
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Mikael Konutgan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md CHANGED
@@ -1,8 +1,11 @@
1
- # Bernoulli : A Ruby library for the binomial distribution
1
+ # Bernoulli: Discrete probability distribution library for Ruby
2
2
 
3
- In probability theory and statistics, the **binomial distribution** is the discrete probability distribution of the number of successes in a sequence of *n* independent yes/no experiments, each of which yields success with probability *p*.
3
+ **Bernoulli** implements the four most common discrete probability distributions in an object oriented manner and in pure Ruby.
4
4
 
5
- You can read more about **Bernoulli trials** and the **binomial distribution** [on Wikipedia](http://en.wikipedia.org/wiki/Binomial_distribution).
5
+ - The binomial distribution
6
+ - The geometric distribution
7
+ - The hypergeometric distribution
8
+ - The Poisson distribution
6
9
 
7
10
  ## Installation
8
11
 
@@ -12,76 +15,66 @@ Use RubyGems to install `bernoulli`
12
15
 
13
16
  ## Tutorial
14
17
 
15
- Using `bernoulli`, one can calculate the probabilities of bernoulli experiments.
18
+ The classes in `bernoulli` reprsent random variables:
16
19
 
17
- Let's start by looking at an example.
20
+ Bernoulli::Distribution::<DistributionName>
21
+
22
+ If, for example you wanted to have a geometrically distributed random variable with parameter 0.43, you would do:
18
23
 
19
- **Question:** What is the chance of getting between 25 and 36 sixes when one rolls a die 180 times? What is the expected value and variance of this trial?
24
+ y = Bernoulli::Distribution::Geometric.new(0.43)
25
+
26
+ Also if you `require 'bernoulli/shorthand'` too, you will get top level shortcut functions to create new instances of all distributions:
20
27
 
21
- Let's use `bernoulli` to solve this:
28
+ - `binomdist`
29
+ - `geomdist`
30
+ - `hgeomdist`
31
+ - `poissondist`
22
32
 
23
- First we load up `irb` from the terminal including `bernoulli` as a library.
33
+ So `y = geomdist(0.43)` would be equivalent to the code shown above.
34
+
35
+ After this you call methods on `y`. The methods avalible to all distributions are:
24
36
 
25
- $ irb -r bernoulli
26
-
27
- Or we could just `require 'bernoulli'` in any Ruby script.
37
+ - `probability`
38
+ - `probability_range`
39
+ - `expected_value`
40
+ - `variance`
41
+ - `standard_deviation`
42
+ - `skewness`
43
+ - `excess`
28
44
 
29
- Then we create a new instance of class Bernoulli and calculate our desired probability and properties like so
45
+ Again, shortcuts include (but this time included automatically):
30
46
 
31
- x = Bernoulli::Distribution.new(180, 1.0/6)
32
- # => #<Bernoulli::Distribution @n=180, @p=0.16666666666666666>
33
-
34
- # The probability of getting between 25 and 36 sixes is
35
- x[25..36] # => 0.7665588897840108
36
-
37
- x.expected_value # => 30.0
38
- x.variance # => 25.0
39
-
40
- We could also calculate the standard deviation, excess or skewness:
41
-
42
- x.standard_deviation # => 5.0
43
- x.excess # => 0.006666666666666665
44
- x.skewness # => 0.13333333333333336
45
-
46
- `bernoulli` can also do empirical tests. Let's look at a smaller example We can simulate the tossing of 4 fair coins
47
+ - `ev` for `expected_value`
48
+ - `v` for `variance`
49
+ - `sd` for `standard_deviation`
50
+ - `[]`, which takes a number or a range and then executes `probability` or `probability_range`
47
51
 
48
- y = Bernoulli::Distribution.new(4, 0.5)
49
- # => #<Bernoulli::Distribution @n=4, @p=0.5>
52
+ ### Example
50
53
 
51
- The method `sample` gives as a random array of length `n`, where each entry is `1` with a probability of `p`. The methods `sample_value` gives us the number of wins in a random expriment, we could than compare it to `expected_value`.
54
+ require 'bernoulli'
55
+ require 'bernoulli/shorthand'
56
+
57
+ x = binomdist(180, 1.0/6)
58
+ # => #<Distribution::Binomial @n=180, @p=0.16666666666666666>
59
+
60
+ x.ev # => 30.0
61
+ x.v # => 25.0
62
+ x[25..36] # => 0.7665588897840108
63
+
64
+ Last, but not least, there are two methods exclusive to the binomial distribution:
52
65
 
53
- y.sample # => [1, 0, 1, 0]
54
- y.sample # => [0, 0, 1, 0]
55
- y.sample # => [1, 1, 1, 1]
66
+ The method `sample` returns a random array of length `n`, where each entry is 1 with a probability of `p`. This is esentially modelling a binomial experiment.
56
67
 
57
- y.sample_value # => 2
58
- y.sample_value # => 1
59
- y.sample_value # => 0
60
- y.sample_value # => 2
61
-
62
- y.expected_value # => 2.0
63
-
64
- Last, but not least, we can create a full table of all possible values and their probabilitys like so
65
-
66
- puts y.table
67
-
68
- will produce
69
-
70
- 0,0.0625
71
- 1,0.25
72
- 2,0.375
73
- 3,0.25
74
- 4,0.0625
68
+ The method `sample_value` returns the number of successes in a random binomial expriment that was executed using `sample`. `sv` is a shortcut for `sample_value`.
75
69
 
76
70
  ## Contributing
77
71
 
78
- `bernoulli` is a really small project. After writing the same code for some project and then losing it two or three times I decided to do it one time and well, so I can just call in the code from here next time.
72
+ `bernoulli` is a small project. After writing the same code for some project and then losing it two or three times I decided to do it one time and well, so I can just call in the code from here next time.
79
73
 
80
- Feel free to cantact me about anything I could/should add or to contribute in any way to this simple library.
74
+ Feel free to cantact me about anything I could/should add or to contribute in any way to this simple library.
81
75
 
82
76
  1. Fork it
83
77
  2. Create your feature branch (`git checkout -b my-new-feature`)
84
78
  3. Commit your changes (`git commit -am 'added some feature'`)
85
79
  4. Push to the branch (`git push origin my-new-feature`)
86
80
  5. Create new Pull Request
87
-
data/Rakefile CHANGED
@@ -1,14 +1,23 @@
1
- require 'rake/testtask'
2
1
  require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+ require 'yard'
3
4
 
4
5
  task :default => :test
5
6
 
6
- Rake::TestTask.new do |test|
7
+ Rake::TestTask.new do |t|
8
+ t.libs << 'test'
9
+ t.pattern = 'test/**/test*.rb'
7
10
  end
8
11
 
9
- desc 'Remove pkg directory'
12
+ YARD::Rake::YardocTask.new do |t|
13
+ t.files = ['lib/**/*.rb']
14
+ t.options = ['--markup=markdown']
15
+ end
16
+
17
+ desc 'Remove pkg and doc directories'
10
18
  task :clean do
11
19
  rm_rf 'pkg/'
20
+ rm_rf 'doc/'
12
21
  end
13
22
 
14
23
  spec = eval File.read('bernoulli.gemspec')
@@ -17,4 +26,3 @@ desc "Remove and uninstall #{spec.name}-#{spec.version}.gem from system gems"
17
26
  task :uninstall => :clean do
18
27
  sh 'gem uninstall bernoulli'
19
28
  end
20
-
@@ -4,22 +4,21 @@ Gem::Specification.new do |spec|
4
4
 
5
5
  spec.name = 'bernoulli'
6
6
  spec.version = Bernoulli::VERSION
7
- spec.summary = 'Binomial experiments library'
8
- spec.description = 'A library that allows calculation of probibilities and properties of binomial experiments like coin tossing'
7
+ spec.summary = 'Discrete probability distribution library for Ruby'
8
+ spec.description = 'Bernoulli implements standard methods used for statistcal calculations with discrete probability distributions in an object oriented manner and in pure Ruby'
9
9
  spec.homepage = 'http://mkonutgan.github.com/bernoulli'
10
10
 
11
11
  spec.author = 'Mikael Konutgan'
12
- spec.email = 'mkonutgan@shortmail.com'
12
+ spec.email = 'mkonutgan@gmail.com'
13
13
 
14
14
  spec.required_ruby_version = '>= 1.8.7'
15
15
  spec.required_rubygems_version = '>= 1.3.6'
16
16
 
17
- spec.files = `git ls-files`.split($\)
18
- spec.test_files = spec.files.grep(/test/)
17
+ spec.files = `git ls-files`.split
18
+ spec.test_files = spec.files.grep(/test_/)
19
19
 
20
- spec.add_development_dependency 'minitest', '~> 3.0.1'
21
- spec.add_development_dependency 'rake', '~> 0.9.2.2'
22
- spec.add_development_dependency 'bundler', '~> 1.1.4'
20
+ spec.add_development_dependency 'minitest', '>= 2.5'
21
+ spec.add_development_dependency 'rake', '>= 0.9'
22
+ spec.add_development_dependency 'bundler', '>= 1.1'
23
23
 
24
24
  end
25
-
@@ -1,85 +1,2 @@
1
- require 'bernoulli/math'
2
1
  require 'bernoulli/version'
3
-
4
- module Bernoulli
5
- class Distribution
6
-
7
- def initialize(n, p)
8
- if n < 0 or p > 1.0 or p < 0.0 or not n.is_a? Integer
9
- raise 'Could not initialize Bernoulli experiment'
10
- end
11
- @n = n
12
- @p = p
13
- end
14
-
15
- def to_s
16
- "#<Bernoulli::Distribution @n=#@n, @p=#@p>"
17
- end
18
-
19
- def probability(k)
20
- Math.binomial(@n, k) * @p**k * (1 - @p)**(@n - k)
21
- end
22
-
23
- def [](k)
24
- if k.is_a? Integer
25
- raise Math::DomainError if not (k <= @n and k >= 0)
26
- probability(k).to_f
27
- elsif k.is_a? Range
28
- raise Math::DomainError if not (k.begin >= 0 and k.end <= @n)
29
- sum = 0
30
- k.each do |i|
31
- sum += probability(i)
32
- end
33
- sum.to_f
34
- else
35
- raise TypeError
36
- end
37
- end
38
-
39
- def sample
40
- s = []
41
- @n.times do
42
- s << (rand < @p ? 1 : 0)
43
- end
44
- s
45
- end
46
-
47
- def sample_value
48
- sample.count(1)
49
- end
50
- alias :sv :sample_value
51
-
52
- def expected_value
53
- @n * @p
54
- end
55
- alias :ev :expected_value
56
-
57
- def variance
58
- @n * @p * (1 - @p)
59
- end
60
- alias :v :variance
61
-
62
- def standard_deviation
63
- Math.sqrt(variance)
64
- end
65
- alias :sd :standard_deviation
66
-
67
- def skewness
68
- (1 - 2 * @p) / (Math.sqrt(@n * @p * (1 - @p)))
69
- end
70
-
71
- def excess
72
- (1 - 6 * @p * (1 - @p)) / (@n * @p * (1 - @p))
73
- end
74
-
75
- def table
76
- csv = ""
77
- (0..@n).each do |n|
78
- csv << n.to_s << "," << probability(n).to_s << "\n"
79
- end
80
- csv
81
- end
82
-
83
- end
84
- end
85
-
2
+ require 'bernoulli/distribution'
@@ -0,0 +1,40 @@
1
+ require 'bernoulli/distribution/binomial'
2
+ require 'bernoulli/distribution/hypergeometric'
3
+ require 'bernoulli/distribution/geometric'
4
+ require 'bernoulli/distribution/poisson'
5
+
6
+ module Bernoulli
7
+
8
+ # Top level Module for all the probability distributions
9
+ # Also provides convinience methods and `#standard_deviation`, which
10
+ # is calculated the same way independent of the distribution
11
+ module Distribution
12
+
13
+ # Calculate the sum of the probabilities across a range
14
+ # @param r [Range]
15
+ def probability_range(r)
16
+ r.inject(0) { |s, k| s + probability(k) }
17
+ end
18
+
19
+ # A shortcut to the `#probability` and `#probability_range`
20
+ # methods
21
+ # @param k [Integer, Range]
22
+ def [](k)
23
+ if k.is_a? Integer
24
+ probability(k).to_f
25
+ elsif k.is_a? Range
26
+ probability_range(k).to_f
27
+ else
28
+ raise TypeError, 'Expecting Integer or Range - "[]"'
29
+ end
30
+ end
31
+
32
+ # The standard deviation of a random variable
33
+ # is the square root of its variance.
34
+ def standard_deviation
35
+ Math.sqrt(variance)
36
+ end
37
+ alias :sd :standard_deviation
38
+
39
+ end
40
+ end
@@ -0,0 +1,71 @@
1
+ require 'bernoulli/math'
2
+
3
+ module Bernoulli
4
+
5
+ module Distribution
6
+
7
+ # Implements binomially distributed random variable
8
+ # See http://en.wikipedia.org/wiki/Binomial_distribution
9
+ # for more information
10
+ class Binomial
11
+
12
+ include Distribution
13
+
14
+ # @param n [Integer] the number of trials (>= 0)
15
+ # @param p [Float] success probability in each trial
16
+ def initialize(n, p)
17
+ if n < 0 or p > 1.0 or p < 0.0
18
+ raise 'Expecting n >= 0 and 0.0 <= p <= 1.0'
19
+ end
20
+ @n = n.to_i
21
+ @p = p.to_f
22
+ end
23
+
24
+ def to_s
25
+ "#<Distribution::Binomial @n=#@n, @p=#@p>"
26
+ end
27
+
28
+ # @param k [Integer] the number of successes (>= 0)
29
+ # @return [Float] the probability of `k` successes
30
+ def probability(k)
31
+ Math.binomial(@n, k) * @p**k * (1 - @p)**(@n - k)
32
+ end
33
+
34
+ # Preform a binomial experiment of length `@n` and probability `@p`
35
+ # @return [Array<0, 1>] the resulting random array
36
+ def sample
37
+ s = []
38
+ @n.times do
39
+ s << (rand < @p ? 1 : 0)
40
+ end
41
+ s
42
+ end
43
+
44
+ # @return [Integer] number of 1's in a run of `#sample`
45
+ def sample_value
46
+ sample.count(1)
47
+ end
48
+ alias :sv :sample_value
49
+
50
+ def expected_value
51
+ @n * @p
52
+ end
53
+ alias :ev :expected_value
54
+
55
+ def variance
56
+ @n * @p * (1 - @p)
57
+ end
58
+ alias :v :variance
59
+
60
+ def skewness
61
+ (1 - 2 * @p) / (Math.sqrt(@n * @p * (1 - @p)))
62
+ end
63
+
64
+ def excess
65
+ (1 - 6 * @p * (1 - @p)) / (@n * @p * (1 - @p))
66
+ end
67
+
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,56 @@
1
+ module Bernoulli
2
+
3
+ module Distribution
4
+
5
+ # Implements geometrically distributed random variable
6
+ # See http://en.wikipedia.org/wiki/Geometric_distribution
7
+ # for more information
8
+ class Geometric
9
+
10
+ include Distribution
11
+
12
+ # @param p [Float] the success probability (>= 0, <= 1)
13
+ def initialize(p)
14
+ if p > 1.0 or p < 0.0
15
+ raise 'Expecting 0.0 <= p <= 1.0'
16
+ end
17
+ @p = p.to_f
18
+ end
19
+
20
+ def to_s
21
+ "#<Distribution::Geometric @p=#@p>"
22
+ end
23
+
24
+ # @param k [Integer] number of independent trials (> 0)
25
+ # @return [Float] the probability that the first occurrence
26
+ # of success require `k` independent trials
27
+ def probability(k)
28
+ if k == 0
29
+ 0
30
+ else
31
+ (1 - @p)**(k - 1) * @p
32
+ end
33
+ end
34
+
35
+ def expected_value
36
+ 1 / @p
37
+ end
38
+ alias :ev :expected_value
39
+
40
+ def variance
41
+ (1 - @p) / @p**2
42
+ end
43
+ alias :v :variance
44
+
45
+ def skewness
46
+ (2 - @p) / Math.sqrt(1 - @p)
47
+ end
48
+
49
+ def excess
50
+ 6 + @p**2 / (1 - @p)
51
+ end
52
+
53
+ end
54
+
55
+ end
56
+ end
@@ -0,0 +1,55 @@
1
+ require 'bernoulli/math'
2
+
3
+ module Bernoulli
4
+
5
+ module Distribution
6
+
7
+ # Implements hypergeometrically distributed random variable
8
+ # See http://en.wikipedia.org/wiki/Hypergeometric_distribution
9
+ # for more information
10
+ class Hypergeometric
11
+
12
+ include Distribution
13
+
14
+ # @param bn [Integer] the size of the population (big n) (> 0)
15
+ # @param m [Integer] the number of successes (>= 0, <= bn)
16
+ # @param n [Integer] the number of draws (>= 1, <= bn)
17
+ def initialize(bn, m, n)
18
+ if bn < 1 or m < 0 or m > bn or n < 1 or n > bn
19
+ raise 'Expecting bn > 1, 0 < m < bn, 0 < n < bn'
20
+ end
21
+ @bn, @m, @n = bn.to_i, m.to_i, n.to_i
22
+ end
23
+
24
+ def to_s
25
+ "#<Distribution::Hypergeometric @bn=#@bn, @m=#@m, @n=#@n>"
26
+ end
27
+
28
+ # @param k [Integer] number of successes (>= 0)
29
+ # @return [Float] the probability of `k` successes
30
+ def probability(k)
31
+ (Math.binomial(@m, k) * Math.binomial(@bn - @m, @n - k)).to_f / Math.binomial(@bn, @n)
32
+ end
33
+
34
+ def expected_value
35
+ @n * (@m.to_f / @bn)
36
+ end
37
+ alias :ev :expected_value
38
+
39
+ def variance
40
+ (@n * @m * (@bn - @m) *(@bn - @n)).to_f / (@bn * @bn * (@bn - 1))
41
+ end
42
+ alias :v :variance
43
+
44
+ def skewness
45
+ ((@bn - 2 * @m) * Math.sqrt(@bn - 1) * (@bn - 2 * @n)) / (Math.sqrt(@n * @m * (@bn - @m) * (@bn - @n)) * (@bn - 2))
46
+ end
47
+
48
+ def excess
49
+ ((@bn - 1) * @bn * @bn * (@bn * (@bn + 1) - 6 * @m * (@bn - @m) - 6 * @n * (@bn - @n)) + 6 * @n * @m * (@bn - @m) * (@bn - @n) * (5 * @bn - 6)).to_f / (@n * @m * (@bn - @m) * (@bn - @n) * (@bn - 2) * (@bn - 3))
50
+ end
51
+
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,58 @@
1
+ require 'bernoulli/math'
2
+
3
+ module Bernoulli
4
+
5
+ module Distribution
6
+
7
+ # Implements Poisson distributed random variable
8
+ # See http://en.wikipedia.org/wiki/Poisson_distribution
9
+ # for more information
10
+ class Poisson
11
+
12
+ include Distribution
13
+
14
+ # @param l [Float] the avarage rate of success in a time period
15
+ def initialize(l)
16
+ if l <= 0.0
17
+ raise 'Expecting l > 0.0'
18
+ end
19
+ @l = l.to_f
20
+ end
21
+
22
+ def to_s
23
+ "#<Distribution::Poisson @l=#@l>"
24
+ end
25
+
26
+ # @param k [Integer] number of successes (>= 0)
27
+ # @return [Float] the probability of `k` successes
28
+ # in the time period
29
+ def probability(k)
30
+ (@l**k / Math.factorial(k)) * Math.exp(-@l)
31
+ end
32
+
33
+ def probability_range(r)
34
+ Math.exp(-@l) * r.inject(0) { |s, k| s + (@l**k / Math.factorial(k)) }
35
+ end
36
+
37
+ def expected_value
38
+ @l
39
+ end
40
+ alias :ev :expected_value
41
+
42
+ def variance
43
+ @l
44
+ end
45
+ alias :v :variance
46
+
47
+ def skewness
48
+ 1 / Math.sqrt(@l)
49
+ end
50
+
51
+ def excess
52
+ 1 / @l
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+ end
@@ -1,8 +1,9 @@
1
+ # Extend the Ruby Math module with common functions used in
2
+ # statstical distributions
1
3
  module Math
2
-
4
+
3
5
  def self.factorial(n)
4
-
5
- if n < 0 or not n.is_a? Integer
6
+ if n < 0
6
7
  raise Math::DomainError, 'Numerical argument is out of domain - "factorial"'
7
8
  end
8
9
  if n == 0
@@ -13,11 +14,11 @@ module Math
13
14
  end
14
15
 
15
16
  def self.binomial(n, k)
16
- if n < 0 or n < k or not (n.is_a? Integer and k.is_a? Integer)
17
- raise Math::DomainError, 'Numerical argument is out of domain - "binomial"'
17
+ if n < 0 or k < 0 or n < k
18
+ 0
19
+ else
20
+ factorial(n)/(factorial(k) * factorial(n - k))
18
21
  end
19
- factorial(n)/(factorial(k) * factorial(n - k))
20
22
  end
21
23
 
22
24
  end
23
-
@@ -0,0 +1,19 @@
1
+ # shorthand that returns new instance of `Distribution::Binomial`
2
+ def binomdist(n, p)
3
+ Bernoulli::Distribution::Binomial.new(n, p)
4
+ end
5
+
6
+ # shorthand that returns new instance of `Distribution::Geometric`
7
+ def geomdist(p)
8
+ Bernoulli::Distribution::Geometric.new(p)
9
+ end
10
+
11
+ # shorthand that returns new instance of `Distribution::Hypergeometric`
12
+ def hgeomdist(bn, m, n)
13
+ Bernoulli::Distribution::Hypergeometric.new(bn, m, n)
14
+ end
15
+
16
+ # shorthand that returns new instance of `Distribution::Poisson`
17
+ def poissondist(l)
18
+ Bernoulli::Distribution::Poisson.new(l)
19
+ end
@@ -1,4 +1,3 @@
1
1
  module Bernoulli
2
- VERSION = "0.3.1"
2
+ VERSION = '0.4'
3
3
  end
4
-
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class BinomialTest < MiniTest::Unit::TestCase
4
+
5
+ def test_new_experiment
6
+ assert_raises RuntimeError do
7
+ Bernoulli::Distribution::Binomial.new(10, 1.1)
8
+ end
9
+ assert_raises RuntimeError do
10
+ Bernoulli::Distribution::Binomial.new(-10, 0.7)
11
+ end
12
+ end
13
+
14
+ def setup
15
+ @x = Bernoulli::Distribution::Binomial.new(180, 1.0/6)
16
+ @y = Bernoulli::Distribution::Binomial.new(2, 0.5)
17
+ end
18
+
19
+ def test_to_s
20
+ assert_equal "#<Distribution::Binomial @n=2, @p=0.5>", @y.to_s
21
+ end
22
+
23
+ def test_coin_toss
24
+ assert_equal 0.25, @y[0]
25
+ assert_equal 0.5, @y[1]
26
+ assert_equal 0.25, @y[2]
27
+ assert_equal 0.75, @y[0..1]
28
+ assert_equal 0.75, @y[1..2]
29
+ assert_equal 1.0, @y[0..2]
30
+ end
31
+
32
+ def test_expected_value
33
+ assert_equal 30, @x.expected_value
34
+ end
35
+
36
+ def test_variance
37
+ assert_equal 25, @x.variance
38
+ end
39
+
40
+ def test_standard_deviation
41
+ assert_equal 5, @x.standard_deviation
42
+ end
43
+
44
+ def test_skewness
45
+ assert_in_eps 0.1333333333333333, @x.skewness
46
+ end
47
+
48
+ def test_excess
49
+ assert_in_eps 0.0066666666666667, @x.excess
50
+ end
51
+
52
+ end
@@ -0,0 +1,43 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class GeometricTest < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @x = Bernoulli::Distribution::Geometric.new(0.5)
7
+ @y = Bernoulli::Distribution::Geometric.new(0.87)
8
+ end
9
+
10
+ def test_to_s
11
+ assert_equal "#<Distribution::Geometric @p=0.5>", @x.to_s
12
+ end
13
+
14
+ def test_probabilities
15
+ assert_in_eps 1.0, @x[1..100]
16
+ assert_in_eps 0.5, @x[1]
17
+ assert_in_eps 0.25, @x[2]
18
+ end
19
+
20
+ def test_expected_value
21
+ assert_in_eps 2, @x.expected_value
22
+ assert_in_eps 1.149425287, @y.expected_value
23
+ end
24
+
25
+ def test_variance
26
+ assert_in_eps 2, @x.variance
27
+ assert_in_eps 0.171753204, @y.variance
28
+ end
29
+
30
+ def test_standard_deviation
31
+ assert_in_eps 1.4142135623730951, @x.standard_deviation
32
+ assert_in_eps 0.414431181, @y.standard_deviation
33
+ end
34
+
35
+ def test_skewness
36
+ assert_in_eps 3.134056109, @y.skewness
37
+ end
38
+
39
+ def test_excess
40
+ assert_in_eps 11.822307692, @y.excess
41
+ end
42
+
43
+ end
@@ -0,0 +1,52 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class HypergeometricTest < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @x = Bernoulli::Distribution::Hypergeometric.new(5, 3, 2)
7
+ @y = Bernoulli::Distribution::Hypergeometric.new(50, 17, 9)
8
+ end
9
+
10
+ def test_to_s
11
+ assert_equal "#<Distribution::Hypergeometric @bn=5, @m=3, @n=2>", @x.to_s
12
+ end
13
+
14
+ def test_probabilities
15
+ assert_in_eps 0.1, @x[0]
16
+ assert_in_eps 0.6, @x[1]
17
+ assert_in_eps 0.3, @x[2]
18
+ assert_in_eps 1.0, @x[0..2]
19
+ assert_in_eps 0.9, @x[1..2]
20
+ assert_in_eps 0.0, @x[3]
21
+ assert_in_eps 0.0, @x[4]
22
+
23
+ assert_in_eps 1.0, @y[0..9]
24
+ assert_in_eps 0.0, @y[10]
25
+ end
26
+
27
+ def test_expected_value
28
+ assert_in_eps 1.2, @x.expected_value
29
+ assert_in_eps 3.06, @y.expected_value
30
+ end
31
+
32
+ def test_variance
33
+ assert_in_eps 0.36, @x.variance
34
+ assert_in_eps 1.689869388, @y.variance
35
+ end
36
+
37
+ def test_standard_deviation
38
+ assert_in_eps 0.6, @x.standard_deviation
39
+ assert_in_eps 1.299949764, @y.standard_deviation
40
+ end
41
+
42
+ def test_skewness
43
+ assert_in_eps -0.111111111, @x.skewness
44
+ assert_in_eps 0.164108906, @y.skewness
45
+ end
46
+
47
+ def test_excess
48
+ assert_in_eps -0.444444444, @x.excess
49
+ assert_in_eps -0.14585017, @y.excess
50
+ end
51
+
52
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path('../../helper', __FILE__)
2
+
3
+ class PoissonTest < MiniTest::Unit::TestCase
4
+
5
+ def setup
6
+ @x = Bernoulli::Distribution::Poisson.new(1)
7
+ @y = Bernoulli::Distribution::Poisson.new(112)
8
+ @z = Bernoulli::Distribution::Poisson.new(54)
9
+ end
10
+
11
+ def test_to_s
12
+ assert_equal "#<Distribution::Poisson @l=1.0>", @x.to_s
13
+ end
14
+
15
+ def test_probabilities_1
16
+ p = [
17
+ 0.36787944117144233,
18
+ 0.36787944117144233,
19
+ 0.18393972058572117,
20
+ 0.061313240195240384,
21
+ 0.015328310048810096,
22
+ 0.0030656620097620196,
23
+ 0.0005109436682936699
24
+ ]
25
+ (0..6).each { |v| assert_in_eps p[v], @x[v] }
26
+ assert_in_eps 1, @x[0..10]
27
+ assert_in_eps 0.9810118431238463, @x[0..3]
28
+ end
29
+
30
+ def test_probabilities_2
31
+ assert_in_eps 0.003324518575716, @y[89]
32
+ assert_in_eps 0.0143492278868432, @y[0..89]
33
+ end
34
+
35
+ def test_probabilities_3
36
+ assert_in_eps 0.0483850390510616, @z[50]
37
+ assert_in_eps 0.32326350500948, @z[0..50]
38
+ assert_in_eps 1.0, @z[0..100]
39
+ end
40
+
41
+ def test_expected_value
42
+ assert_equal 1, @x.expected_value
43
+ assert_equal 112, @y.expected_value
44
+ end
45
+
46
+ def test_variance
47
+ assert_equal 1, @x.variance
48
+ assert_equal 112, @y.variance
49
+ end
50
+
51
+ def test_standard_deviation
52
+ assert_in_eps 1, @x.standard_deviation
53
+ assert_in_eps Math.sqrt(112), @y.standard_deviation
54
+ end
55
+
56
+ def test_skewness
57
+ assert_in_eps 0.094491118, @y.skewness
58
+ end
59
+
60
+ def test_excess
61
+ assert_in_eps 0.008928571, @y.excess
62
+ end
63
+
64
+ end
@@ -0,0 +1,12 @@
1
+ require 'minitest/unit'
2
+ require 'minitest/pride'
3
+
4
+ require 'bernoulli/distribution'
5
+
6
+ class MiniTest::Unit::TestCase
7
+
8
+ def assert_in_eps exp, act
9
+ assert_in_delta exp, act, 1.0e-7
10
+ end
11
+
12
+ end
@@ -1,24 +1,22 @@
1
1
  require 'minitest/autorun'
2
2
  require 'minitest/pride'
3
- require 'bernoulli'
3
+ require 'bernoulli/math'
4
4
 
5
5
  class MathTest < MiniTest::Unit::TestCase
6
6
 
7
7
  def test_factorial
8
8
  assert_raises(Math::DomainError) { Math.factorial(-1) }
9
- assert_raises(Math::DomainError) { Math.factorial(2.4) }
10
9
  assert_equal 1, Math.factorial(0)
11
10
  assert_equal 1, Math.factorial(1)
11
+ assert_equal 2, Math.factorial(2)
12
12
  assert_equal 120, Math.factorial(5)
13
13
  assert_equal 263130836933693530167218012160000000, Math.factorial(32)
14
14
  end
15
15
 
16
16
  def test_binomial
17
- pairs = [[-1, 0], [2, 4], [-2, -1], [1.2, 3.4], [12, 50]]
17
+ pairs = [[-1, 0], [2, 4], [-2, -1], [6, -3], [12, 50]]
18
18
  pairs.each do |pair|
19
- assert_raises Math::DomainError do
20
- Math.binomial *pair
21
- end
19
+ assert_equal 0, Math.binomial(*pair)
22
20
  end
23
21
  assert_equal 1, Math.binomial(0, 0)
24
22
  (1..20).each do |k|
@@ -36,4 +34,3 @@ class MathTest < MiniTest::Unit::TestCase
36
34
  end
37
35
 
38
36
  end
39
-
@@ -0,0 +1,26 @@
1
+ require 'bernoulli/distribution'
2
+ require 'bernoulli/shorthand'
3
+
4
+ class ShorthandTest < MiniTest::Unit::TestCase
5
+
6
+ def test_binomdist
7
+ x = Bernoulli::Distribution::Binomial.new(10, 0.71)
8
+ assert_equal x.to_s, binomdist(10, 0.71).to_s
9
+ end
10
+
11
+ def test_geomdist
12
+ x = Bernoulli::Distribution::Geometric.new(0.53)
13
+ assert_equal x.to_s, geomdist(0.53).to_s
14
+ end
15
+
16
+ def test_hgeomdist
17
+ x = Bernoulli::Distribution::Hypergeometric.new(20, 14, 5)
18
+ assert_equal x.to_s, hgeomdist(20, 14, 5).to_s
19
+ end
20
+
21
+ def test_poissondist
22
+ x = Bernoulli::Distribution::Poisson.new(13.3)
23
+ assert_equal x.to_s, poissondist(13.3).to_s
24
+ end
25
+
26
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bernoulli
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.1
4
+ version: '0.4'
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,72 +9,85 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-09 00:00:00.000000000 Z
12
+ date: 2012-07-04 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 3.0.1
21
+ version: '2.5'
22
22
  type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ~>
27
+ - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 3.0.1
29
+ version: '2.5'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rake
32
32
  requirement: !ruby/object:Gem::Requirement
33
33
  none: false
34
34
  requirements:
35
- - - ~>
35
+ - - ! '>='
36
36
  - !ruby/object:Gem::Version
37
- version: 0.9.2.2
37
+ version: '0.9'
38
38
  type: :development
39
39
  prerelease: false
40
40
  version_requirements: !ruby/object:Gem::Requirement
41
41
  none: false
42
42
  requirements:
43
- - - ~>
43
+ - - ! '>='
44
44
  - !ruby/object:Gem::Version
45
- version: 0.9.2.2
45
+ version: '0.9'
46
46
  - !ruby/object:Gem::Dependency
47
47
  name: bundler
48
48
  requirement: !ruby/object:Gem::Requirement
49
49
  none: false
50
50
  requirements:
51
- - - ~>
51
+ - - ! '>='
52
52
  - !ruby/object:Gem::Version
53
- version: 1.1.4
53
+ version: '1.1'
54
54
  type: :development
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  none: false
58
58
  requirements:
59
- - - ~>
59
+ - - ! '>='
60
60
  - !ruby/object:Gem::Version
61
- version: 1.1.4
62
- description: A library that allows calculation of probibilities and properties of
63
- binomial experiments like coin tossing
64
- email: mkonutgan@shortmail.com
61
+ version: '1.1'
62
+ description: Bernoulli implements standard methods used for statistcal calculations
63
+ with discrete probability distributions in an object oriented manner and in pure
64
+ Ruby
65
+ email: mkonutgan@gmail.com
65
66
  executables: []
66
67
  extensions: []
67
68
  extra_rdoc_files: []
68
69
  files:
69
70
  - Gemfile
71
+ - LICENSE.md
70
72
  - README.md
71
73
  - Rakefile
72
74
  - bernoulli.gemspec
73
75
  - lib/bernoulli.rb
76
+ - lib/bernoulli/distribution.rb
77
+ - lib/bernoulli/distribution/binomial.rb
78
+ - lib/bernoulli/distribution/geometric.rb
79
+ - lib/bernoulli/distribution/hypergeometric.rb
80
+ - lib/bernoulli/distribution/poisson.rb
74
81
  - lib/bernoulli/math.rb
82
+ - lib/bernoulli/shorthand.rb
75
83
  - lib/bernoulli/version.rb
76
- - test/test_bernoulli.rb
84
+ - test/distribution/test_binomial.rb
85
+ - test/distribution/test_geometric.rb
86
+ - test/distribution/test_hypergeometric.rb
87
+ - test/distribution/test_poisson.rb
88
+ - test/helper.rb
77
89
  - test/test_math.rb
90
+ - test/test_shorthand.rb
78
91
  homepage: http://mkonutgan.github.com/bernoulli
79
92
  licenses: []
80
93
  post_install_message:
@@ -98,7 +111,12 @@ rubyforge_project:
98
111
  rubygems_version: 1.8.24
99
112
  signing_key:
100
113
  specification_version: 3
101
- summary: Binomial experiments library
114
+ summary: Discrete probability distribution library for Ruby
102
115
  test_files:
103
- - test/test_bernoulli.rb
116
+ - test/distribution/test_binomial.rb
117
+ - test/distribution/test_geometric.rb
118
+ - test/distribution/test_hypergeometric.rb
119
+ - test/distribution/test_poisson.rb
104
120
  - test/test_math.rb
121
+ - test/test_shorthand.rb
122
+ has_rdoc:
@@ -1,61 +0,0 @@
1
- require 'minitest/autorun'
2
- require 'minitest/pride'
3
- require 'bernoulli'
4
-
5
- class DistributionTest < MiniTest::Unit::TestCase
6
-
7
- def test_new_experiment
8
- assert_raises RuntimeError do
9
- Bernoulli::Distribution.new(10, 1.1)
10
- end
11
- assert_raises RuntimeError do
12
- Bernoulli::Distribution.new(-10, 0.7)
13
- end
14
- assert_raises RuntimeError do
15
- Bernoulli::Distribution.new(4.5, 0.2)
16
- end
17
- end
18
-
19
- def setup
20
- @x = Bernoulli::Distribution.new(180, 1.0/6)
21
- @y = Bernoulli::Distribution.new(2, 0.5)
22
- @z = Bernoulli::Distribution.new(4, 0.5)
23
- end
24
-
25
- def test_to_s
26
- assert_equal "#<Bernoulli::Distribution @n=2, @p=0.5>", @y.to_s
27
- end
28
-
29
- def test_coin_toss
30
- assert_equal 0.5, @y[1]
31
- assert_equal 0.25, @y[2]
32
- assert_equal 1.0, @y[0..2]
33
- end
34
-
35
- def test_expected_value
36
- assert_equal 30, @x.expected_value
37
- end
38
-
39
- def test_variance
40
- assert_equal 25, @x.variance
41
- end
42
-
43
- def test_standard_deviation
44
- assert_equal 5, @x.standard_deviation
45
- end
46
-
47
- def test_skewness
48
- assert_in_delta 0.1333333333333333, @x.skewness, 1.0e-7
49
- end
50
-
51
- def test_excess
52
- assert_in_delta 0.0066666666666667, @x.excess, 1.0e-7
53
- end
54
-
55
- def test_table
56
- str = "0,0.0625\n1,0.25\n2,0.375\n3,0.25\n4,0.0625\n"
57
- assert_equal str, @z.table
58
- end
59
-
60
- end
61
-