capricious 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/CHANGES CHANGED
@@ -1,4 +1,8 @@
1
- version 0.2.1
1
+ version 0.2.2
2
+
3
+ * Added Normal distribution
4
+
5
+ version 0.2.1 (7e4db0b4f1ab5eaa784708c9678aefe1d0ad9f16)
2
6
 
3
7
  * 0.2.0 sneaked out the door with a stray debugging printf; this is a paper-bag release.
4
8
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.1
1
+ 0.2.2
@@ -24,3 +24,4 @@ require 'capricious/biased_uniform'
24
24
  require 'capricious/poisson'
25
25
  require 'capricious/exponential'
26
26
  require 'capricious/erlang'
27
+ require 'capricious/normal'
@@ -0,0 +1,59 @@
1
+ # capricious/normal.rb: Normal distribution PRNG, with selectable source-randomness policy
2
+ #
3
+ # Copyright:: Copyright (c) 2010 Red Hat, Inc.
4
+ # Author:: William Benton <willb@redhat.com>
5
+ # License:: http://www.apache.org/licenses/LICENSE-2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+
19
+ require 'capricious/generic_prng'
20
+
21
+ module Capricious
22
+ # Normal-distribution PRNG, uses polar form of Box-Muller transform.
23
+ class Normal
24
+ include PRNG
25
+
26
+ attr_reader :expected_mean, :expected_variance
27
+
28
+ # Initializes a new distribution. mean and variance are the distribution parameters; =seed=,
29
+ # =policy=, and =keep_stats= are as in =PRNG=.
30
+ def initialize(mean, variance, seed=nil, policy=MWC5, keep_stats=false)
31
+ @expected_mean = mean.to_f
32
+ @expected_variance = variance.to_f
33
+ @stddev = Math.sqrt(@expected_variance)
34
+ @values = []
35
+ prng_initialize(seed, policy, keep_stats)
36
+ end
37
+
38
+ private
39
+ def next_value
40
+ return @values.pop if @values.size() > 0
41
+ u, v, r = 0, 0, 0
42
+
43
+ begin
44
+ u = 2 * @prng.next_f - 1
45
+ v = 2 * @prng.next_f - 1
46
+ r = u ** 2 + v ** 2
47
+ end while r == 0 || r > 1
48
+
49
+ c = Math.sqrt(-2 * Math.log(r) / r)
50
+
51
+ @values << scale(v * c)
52
+ scale(u * c)
53
+ end
54
+
55
+ def scale(val)
56
+ @expected_mean + (val * @stddev)
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,34 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ module Capricious
4
+ SAMPLE_COUNT = 30000
5
+
6
+ describe Normal do
7
+ def generate_samples(policy, mean, variance, count=SAMPLE_COUNT)
8
+ @normal = Capricious::Normal.new(mean, variance, nil, policy, true)
9
+ count.times {@normal.next}
10
+ end
11
+
12
+ [LFSR,MWC5].each do |policy|
13
+ [[0.0,1.0], [10.0,3.5]].each do |mean, variance|
14
+
15
+ it "should, given policy #{policy.name}, generate normally-distributed numbers with a mean of #{mean} and a variance of #{variance}, as judged by mean estimates" do
16
+ generate_samples(policy, mean, variance)
17
+ @normal.aggregate.mean.should be_close(@normal.expected_mean, 0.01 * [mean, 1.0].max)
18
+ end
19
+
20
+ it "should, given policy #{policy.name}, generate normally-distributed numbers with a mean of #{mean} and a variance of #{variance}, as judged by variance estimates" do
21
+ generate_samples(policy, mean, variance)
22
+ @normal.aggregate.stddev.should be_close(Math.sqrt(@normal.expected_variance), 0.075 * variance)
23
+ end
24
+ end
25
+
26
+ it "should, given policy #{policy.name}, generate the same sequence given the same seed" do
27
+ @normal = Normal.new(0.0, 1.0, nil, policy, false)
28
+ @normal2 = Normal.new(0.0, 1.0, nil, policy, false)
29
+ (SAMPLE_COUNT/10).times { @normal2.next.should == @normal.next }
30
+ end
31
+
32
+ end
33
+ end
34
+ end
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 2
8
- - 1
9
- version: 0.2.1
8
+ - 2
9
+ version: 0.2.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Will Benton
@@ -55,12 +55,14 @@ files:
55
55
  - lib/capricious/generic_prng.rb
56
56
  - lib/capricious/lfsr.rb
57
57
  - lib/capricious/mwc5.rb
58
+ - lib/capricious/normal.rb
58
59
  - lib/capricious/poisson.rb
59
60
  - lib/capricious/sample_sink.rb
60
61
  - lib/capricious/uniform.rb
61
62
  - spec/biased_uniform_spec.rb
62
63
  - spec/erlang_spec.rb
63
64
  - spec/exponential_spec.rb
65
+ - spec/normal_spec.rb
64
66
  - spec/poisson_spec.rb
65
67
  - spec/spec.opts
66
68
  - spec/spec_helper.rb
@@ -99,6 +101,7 @@ test_files:
99
101
  - spec/biased_uniform_spec.rb
100
102
  - spec/erlang_spec.rb
101
103
  - spec/exponential_spec.rb
104
+ - spec/normal_spec.rb
102
105
  - spec/poisson_spec.rb
103
106
  - spec/spec_helper.rb
104
107
  - spec/uniform_spec.rb