bernoulli 0.3.1 → 0.4

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