erv 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/Gemfile +4 -0
- data/LICENSE +20 -0
- data/README.md +95 -0
- data/Rakefile +55 -0
- data/erv.gemspec +33 -0
- data/lib/erv.rb +10 -0
- data/lib/erv/constant_distribution.rb +15 -0
- data/lib/erv/discrete_uniform_distribution.rb +32 -0
- data/lib/erv/distribution.rb +16 -0
- data/lib/erv/exponential_distribution.rb +31 -0
- data/lib/erv/gamma_distribution.rb +32 -0
- data/lib/erv/gaussian_distribution.rb +32 -0
- data/lib/erv/general_pareto_distribution.rb +42 -0
- data/lib/erv/geometric_distribution.rb +32 -0
- data/lib/erv/random_variable.rb +43 -0
- data/lib/erv/rng.rb +29 -0
- data/lib/erv/support/try.rb +15 -0
- data/lib/erv/uniform_distribution.rb +33 -0
- data/lib/erv/version.rb +3 -0
- data/spec/erv/constant_distribution_spec.rb +29 -0
- data/spec/spec_helper.rb +20 -0
- metadata +123 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 0116fa6cb4d3e6b11d3602ed2608b6b60a90f717
|
4
|
+
data.tar.gz: aac7790d8d9f9ab82e5ed0c70157cc7e95ef3398
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 94cc7f3280ae54020481e86d0e1caa181b539b0d8d6ca31e436e0eb4ed6ff0c12d000b9fc8443e32cb137aec706ef3b2831b1676d1751959c1c333cf72035ab4
|
7
|
+
data.tar.gz: 5fb06905713c33f6fd563849c7c44ceae643a272cc52250a4a41cdaa6c01a9a79e334abe1d679a13ce833820e4b58b045f68d3b619d8fd123e6fbbd806a01904
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2014 Mauro Tortonesi
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
6
|
+
this software and associated documentation files (the "Software"), to deal in
|
7
|
+
the Software without restriction, including without limitation the rights to
|
8
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
9
|
+
the Software, and to permit persons to whom the Software is furnished to do so,
|
10
|
+
subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
17
|
+
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
18
|
+
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
19
|
+
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
20
|
+
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
# ruby-erv
|
2
|
+
|
3
|
+
Easy/elegant random variable library
|
4
|
+
|
5
|
+
|
6
|
+
## Description
|
7
|
+
|
8
|
+
ruby-erv is a library that enables to create objects representing random
|
9
|
+
variables with a given probability distribution (gaussian, uniform, etc.) and
|
10
|
+
to sample from them. ruby-erv was built from code that I extracted out of
|
11
|
+
several scientific software I wrote for my research projects.
|
12
|
+
|
13
|
+
ruby-erv is designed to work on both YARV/MRI and JRuby. I have not tested it
|
14
|
+
on Rubinius yet.
|
15
|
+
|
16
|
+
|
17
|
+
## Installation
|
18
|
+
|
19
|
+
I have not released ruby-erv on RubyGems, yet. For the moment, if you want to
|
20
|
+
try it just place this line:
|
21
|
+
|
22
|
+
```ruby
|
23
|
+
gem 'erv', git: 'https://github.com/mtortonesi/ruby-erv.git'
|
24
|
+
```
|
25
|
+
|
26
|
+
in your Gemfile and run:
|
27
|
+
|
28
|
+
bundle install
|
29
|
+
|
30
|
+
If using JRuby, you'll also need to run:
|
31
|
+
|
32
|
+
rake get_latest_commons_math_snapshot
|
33
|
+
|
34
|
+
to fetch the latest version of Apache Commons Math 3.3-SNAPSHOT. See the
|
35
|
+
[implementation notes below](#implementation-notes) for more information. (Note
|
36
|
+
that the rake-based installation of Apache Commons Math 3.3-SNAPSHOT requires
|
37
|
+
[nokogiri](http://nokogiri.org/).)
|
38
|
+
|
39
|
+
|
40
|
+
## Examples
|
41
|
+
|
42
|
+
Here is a rather self-explanatory example demonstrating how to create random
|
43
|
+
variables using ruby-erv, and how to sample from them:
|
44
|
+
|
45
|
+
```ruby
|
46
|
+
require 'erv'
|
47
|
+
|
48
|
+
gaussian_rv = ERV::RandomVariable.new(distribution: :gaussian,
|
49
|
+
mean: 10, sd: 2)
|
50
|
+
s1 = gaussian_rv.sample
|
51
|
+
```
|
52
|
+
|
53
|
+
|
54
|
+
## Implementation notes
|
55
|
+
|
56
|
+
In YARV/MRI, ruby-erv leverages the GNU Scientific Library (GSL) for random
|
57
|
+
number generation according to the desired probability distribution.
|
58
|
+
Unfortunately, ruby-gsl is unmaintained and broken. (See [the
|
59
|
+
patch](http://rubyforge.org/tracker/?func=detail&atid=1169&aid=29353&group_id=285)
|
60
|
+
that I sent them ages ago and that was never merged.) So, ruby-erv uses the
|
61
|
+
[gsl-nmatrix](https://github.com/SciRuby/rb-gsl) fork of ruby-gsl.
|
62
|
+
|
63
|
+
In JRuby, ruby-erv leverages the [Apache Commons
|
64
|
+
Math](http://commons.apache.org/proper/commons-math/) library to access the
|
65
|
+
same random number generation functions. Unfortunately, at the time of this
|
66
|
+
writing the Apache Commons Math maintainers have not shipped the 3.3 release
|
67
|
+
yet. Commons Math 3.3 should include support for geometric distribution (that I
|
68
|
+
need for several of my projects), thanks to [a
|
69
|
+
patch](https://issues.apache.org/jira/browse/MATH-973) that I submitted and
|
70
|
+
that was merged some time ago. So, for the moment ruby-env builds on top of the
|
71
|
+
3.3-SNAPSHOT version of Apache Commons Math.
|
72
|
+
|
73
|
+
To facilitate the installation of ruby-env under JRuby, I have decided to
|
74
|
+
bundle the jar archive of Apache Commons Math 3.3-SNAPSHOT in (the jars
|
75
|
+
directory of) the ruby-env gem package. This is a rather dirty but not uncommon
|
76
|
+
approach, as many other gems (including the awesome
|
77
|
+
[Nokogiri](https://github.com/sparklemotion/nokogiri/tree/master/lib)) bundle
|
78
|
+
external jar dependencies in their JRuby version. However, in future I might
|
79
|
+
decide to switch to a more powerful, Maven-based automated installation of
|
80
|
+
Apache Commons Math 3.3-SNAPSHOT. For instance, based on Christian Meier's
|
81
|
+
[jar-dependencies](https://github.com/mkristian/jar-dependencies).
|
82
|
+
|
83
|
+
|
84
|
+
## Acknowledgment
|
85
|
+
|
86
|
+
I would like to thank [Christian Meier](https://github.com/mkristian) for his
|
87
|
+
very valuable suggestions on how to package this gem for JRuby. If you're
|
88
|
+
interested in building serious applications for JRuby, I strongly recommend you
|
89
|
+
to check out Christian's [jbundler](https://github.com/mkristian/jbundler) and
|
90
|
+
[jar-dependencies](https://github.com/mkristian/jar-dependencies).
|
91
|
+
|
92
|
+
|
93
|
+
## License
|
94
|
+
|
95
|
+
MIT
|
data/Rakefile
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
if RUBY_PLATFORM =~ /java/
|
2
|
+
|
3
|
+
require 'lib/erv/version'
|
4
|
+
require 'bundler/gem_helper'
|
5
|
+
|
6
|
+
require 'nokogiri'
|
7
|
+
require 'open-uri'
|
8
|
+
|
9
|
+
# setup absolute path for jars directory
|
10
|
+
JAR_DIR = File.expand_path(File.join(File.dirname(__FILE__), 'jars'))
|
11
|
+
|
12
|
+
directory JAR_DIR
|
13
|
+
|
14
|
+
desc 'Get latest snapshot of Apache Commons Math 3.3'
|
15
|
+
task :get_latest_commons_math_snapshot => [ JAR_DIR ] do
|
16
|
+
# base URL of the apache commons math 3 snapshot repository
|
17
|
+
BASE_URL = 'http://repository.apache.org/content/groups/snapshots/org/apache/commons/commons-math3/3.3-SNAPSHOT/'
|
18
|
+
|
19
|
+
# retrieve timestamp and build number of latest snapshot
|
20
|
+
puts 'Retrieving metadata information on latest Apache Commons Math 3.3 snapshot.'
|
21
|
+
doc = Nokogiri::HTML(open(BASE_URL + 'maven-metadata.xml'))
|
22
|
+
timestamp = doc.xpath('//timestamp/text()')
|
23
|
+
buildnumber = doc.xpath('//buildnumber/text()')
|
24
|
+
|
25
|
+
# get archive name of latest snapshot
|
26
|
+
filename = "commons-math3-3.3-#{timestamp}-#{buildnumber}.jar"
|
27
|
+
|
28
|
+
# get destination file name
|
29
|
+
jar_path = File.join(JAR_DIR, filename)
|
30
|
+
|
31
|
+
# don't download if file already exists
|
32
|
+
if File.exists?(jar_path)
|
33
|
+
puts 'Archive already present in jars directory.'
|
34
|
+
else
|
35
|
+
puts 'Retrieving latest Apache Commons Math 3.3 snapshot.'
|
36
|
+
file_url = BASE_URL + filename
|
37
|
+
File.write(jar_path, open(file_url).read)
|
38
|
+
end
|
39
|
+
|
40
|
+
# clean JAR_DIR of every file except filename
|
41
|
+
puts 'Removing obsolete archives from jars directory.'
|
42
|
+
FileUtils.rm(Dir.glob("#{JAR_DIR}/*").reject!{|file| file == jar_path })
|
43
|
+
end
|
44
|
+
|
45
|
+
desc "Build erv-#{ERV::VERSION}-java.gem into the pkg directory."
|
46
|
+
task :build => [ :get_latest_commons_math_snapshot ] do
|
47
|
+
Bundler::GemHelper.instance = Bundler::GemHelper.new
|
48
|
+
Bundler::GemHelper.instance.build_gem
|
49
|
+
end
|
50
|
+
|
51
|
+
else # RUBY_PLATFORM !~ /java/
|
52
|
+
|
53
|
+
require 'bundler/gem_tasks'
|
54
|
+
|
55
|
+
end
|
data/erv.gemspec
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'erv/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'erv'
|
8
|
+
spec.version = ERV::VERSION
|
9
|
+
spec.authors = ['Mauro Tortonesi']
|
10
|
+
spec.email = ['mauro.tortonesi@unife.it']
|
11
|
+
spec.description = "erv-#{ERV::VERSION}"
|
12
|
+
spec.summary = %q{Easy/elegant Ruby library providing support for random variable generation}
|
13
|
+
spec.homepage = 'https://github.com/mtortonesi/ruby-erv'
|
14
|
+
spec.license = 'MIT'
|
15
|
+
|
16
|
+
spec.files = `git ls-files`.split($/).reject{|x| x == '.gitignore' }
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_development_dependency 'bundler', '~> 1.3'
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rspec'
|
24
|
+
|
25
|
+
if RUBY_PLATFORM =~ /java/
|
26
|
+
# we need to release a JRuby-specific gem
|
27
|
+
spec.platform = 'java'
|
28
|
+
# include Apache Commons Math 3.3 jar archive
|
29
|
+
spec.files.concat(Dir['jars/*.jar'])
|
30
|
+
else
|
31
|
+
spec.add_dependency 'gsl-nmatrix'
|
32
|
+
end
|
33
|
+
end
|
data/lib/erv.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
# Load Apache Commons Math 3.3 jar if we're using JRuby
|
2
|
+
if RUBY_PLATFORM =~ /java/
|
3
|
+
JARS_DIR = File.expand_path(File.join(File.dirname(__FILE__), '..', 'jars'))
|
4
|
+
Dir["#{JARS_DIR}/*.jar"].each do |jar|
|
5
|
+
$CLASSPATH << jar unless $CLASSPATH.include?(jar)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'erv/version'
|
10
|
+
require 'erv/random_variable'
|
@@ -0,0 +1,32 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
java_import org.apache.commons.math3.distribution.UniformIntegerDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'erv/distribution'
|
7
|
+
require 'erv/support/try'
|
8
|
+
|
9
|
+
|
10
|
+
module ERV
|
11
|
+
|
12
|
+
class DiscreteUniformDistribution < Distribution
|
13
|
+
def initialize(opts)
|
14
|
+
super(opts)
|
15
|
+
|
16
|
+
raise ArgumentError unless opts[:max_value]
|
17
|
+
max = opts[:max_value].to_i
|
18
|
+
min = opts[:min_value].try(:to_i) || 0
|
19
|
+
|
20
|
+
if RUBY_PLATFORM == 'java'
|
21
|
+
# create distribution
|
22
|
+
d = UniformIntegerDistribution.new(@rng, min, max)
|
23
|
+
# setup sampling function
|
24
|
+
@func = Proc.new { d.sample }
|
25
|
+
else
|
26
|
+
# setup sampling function
|
27
|
+
@func = Proc.new { min + @rng.uniform_int(max-min) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
JExponentialDistribution = org.apache.commons.math3.distribution.ExponentialDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'erv/distribution'
|
7
|
+
|
8
|
+
|
9
|
+
module ERV
|
10
|
+
|
11
|
+
class ExponentialDistribution < Distribution
|
12
|
+
def initialize(opts)
|
13
|
+
super(opts)
|
14
|
+
|
15
|
+
raise ArgumentError unless opts[:mean]
|
16
|
+
mean = opts[:mean].to_f
|
17
|
+
|
18
|
+
if RUBY_PLATFORM == 'java'
|
19
|
+
# create distribution
|
20
|
+
d = JExponentialDistribution.new(@rng, mean,
|
21
|
+
JExponentialDistribution::DEFAULT_INVERSE_ABSOLUTE_ACCURACY)
|
22
|
+
# setup sampling function
|
23
|
+
@func = Proc.new { d.sample }
|
24
|
+
else
|
25
|
+
# setup sampling function
|
26
|
+
@func = Proc.new { @rng.exponential(mean) }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
JGammaDistribution = org.apache.commons.math3.distribution.GammaDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'erv/distribution'
|
7
|
+
|
8
|
+
|
9
|
+
module ERV
|
10
|
+
|
11
|
+
class GammaDistribution < Distribution
|
12
|
+
def initialize(opts)
|
13
|
+
super(opts)
|
14
|
+
|
15
|
+
raise ArgumentError unless opts[:rate] and opts[:shape]
|
16
|
+
scale = 1 / opts[:rate].to_f
|
17
|
+
shape = opts[:shape].to_f
|
18
|
+
|
19
|
+
if RUBY_PLATFORM == 'java'
|
20
|
+
# create distribution
|
21
|
+
d = JGammaDistribution.new(@rng, shape, scale,
|
22
|
+
JGammaDistribution::DEFAULT_INVERSE_ABSOLUTE_ACCURACY)
|
23
|
+
# setup sampling function
|
24
|
+
@func = Proc.new { d.sample }
|
25
|
+
else
|
26
|
+
# setup sampling function
|
27
|
+
@func = Proc.new { @rng.gamma(shape, scale) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
java_import org.apache.commons.math3.distribution.NormalDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'erv/distribution'
|
7
|
+
|
8
|
+
|
9
|
+
module ERV
|
10
|
+
|
11
|
+
class GaussianDistribution < Distribution
|
12
|
+
def initialize(opts)
|
13
|
+
super(opts)
|
14
|
+
|
15
|
+
raise ArgumentError unless opts[:mean] and opts[:sd]
|
16
|
+
mean = opts[:mean].to_f
|
17
|
+
sd = opts[:sd].to_f
|
18
|
+
|
19
|
+
if RUBY_PLATFORM == 'java'
|
20
|
+
# create distribution
|
21
|
+
d = NormalDistribution.new(@rng, mean, sd,
|
22
|
+
NormalDistribution::DEFAULT_INVERSE_ABSOLUTE_ACCURACY)
|
23
|
+
# setup sampling function
|
24
|
+
@func = Proc.new { d.sample }
|
25
|
+
else
|
26
|
+
# setup sampling function
|
27
|
+
@func = Proc.new { mean + @rng.ran_gaussian(sd) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
java_import org.apache.commons.math3.distribution.UniformRealDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'erv/distribution'
|
7
|
+
require 'erv/support/try'
|
8
|
+
|
9
|
+
|
10
|
+
module ERV
|
11
|
+
|
12
|
+
class GpdDistribution < Distribution
|
13
|
+
def initialize(opts)
|
14
|
+
super(opts)
|
15
|
+
|
16
|
+
raise ArgumentError unless opts[:scale] and opts[:shape]
|
17
|
+
scale = opts[:scale].to_f
|
18
|
+
shape = opts[:shape].to_f
|
19
|
+
location = opts[:location].try(:to_f) || 0.0
|
20
|
+
|
21
|
+
if RUBY_PLATFORM == 'java'
|
22
|
+
# create uniform distribution
|
23
|
+
d = UniformRealDistribution.new(@rng, 0.0, 1.0,
|
24
|
+
UniformRealDistribution::DEFAULT_INVERSE_ABSOLUTE_ACCURACY)
|
25
|
+
# setup sampling function
|
26
|
+
@func = Proc.new {
|
27
|
+
# this algorithm was taken from wikipedia
|
28
|
+
u = 1.0 - d.sample
|
29
|
+
location + (scale * ((u ** (-shape)) - 1.0) / shape)
|
30
|
+
}
|
31
|
+
else
|
32
|
+
# setup sampling function
|
33
|
+
@func = Proc.new {
|
34
|
+
# this algorithm was taken from wikipedia
|
35
|
+
u = 1.0 - @rng.uniform
|
36
|
+
location + (scale * ((u ** (-shape)) - 1.0) / shape)
|
37
|
+
}
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
JGeometricDistribution = org.apache.commons.math3.distribution.GeometricDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
|
7
|
+
module ERV
|
8
|
+
|
9
|
+
class GeometricDistribution < Distribution
|
10
|
+
def initialize(opts)
|
11
|
+
super(opts)
|
12
|
+
|
13
|
+
raise ArgumentError unless opts[:probability_of_success]
|
14
|
+
p = opts[:probability_of_success].to_f
|
15
|
+
|
16
|
+
if RUBY_PLATFORM == 'java'
|
17
|
+
# create distribution
|
18
|
+
d = JGeometricDistribution.new(@rng, p)
|
19
|
+
# setup sampling function
|
20
|
+
@func = Proc.new { d.sample }
|
21
|
+
else
|
22
|
+
# setup sampling function
|
23
|
+
#
|
24
|
+
# WARNING: I HAVEN'T TRIED THIS CODE!!!
|
25
|
+
# Note that GSL implements the shifted version of the geometric
|
26
|
+
# distribution, so we might need to change the result (removing 1?)
|
27
|
+
@func = Proc.new { @rng.geometric(p) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'erv/constant_distribution'
|
2
|
+
require 'erv/discrete_uniform_distribution'
|
3
|
+
require 'erv/exponential_distribution'
|
4
|
+
require 'erv/gamma_distribution'
|
5
|
+
require 'erv/gaussian_distribution'
|
6
|
+
require 'erv/general_pareto_distribution'
|
7
|
+
require 'erv/geometric_distribution'
|
8
|
+
require 'erv/uniform_distribution'
|
9
|
+
require 'erv/support/try'
|
10
|
+
|
11
|
+
|
12
|
+
module ERV
|
13
|
+
|
14
|
+
class RandomVariable
|
15
|
+
def initialize(opts)
|
16
|
+
# get distribution name
|
17
|
+
dist_name = opts[:distribution].try(:to_s)
|
18
|
+
|
19
|
+
# get class name that corresponds to the requested distribution
|
20
|
+
klass_name = dist_name.split('_').push('distribution').map(&:capitalize).join
|
21
|
+
# create distribution object
|
22
|
+
@dist = ERV.const_get(klass_name).new(opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
def next
|
26
|
+
@dist.sample
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
class SequentialRandomVariable
|
32
|
+
def initialize(args)
|
33
|
+
@first = args.delete(:first_value)
|
34
|
+
@most_recent = @first || 0.0
|
35
|
+
@var = RandomVariable.new(args)
|
36
|
+
end
|
37
|
+
|
38
|
+
def next
|
39
|
+
@most_recent += @var.next
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/lib/erv/rng.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
java_import org.apache.commons.math3.random.MersenneTwister
|
4
|
+
else
|
5
|
+
require 'gsl'
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
module ERV
|
10
|
+
|
11
|
+
class RNG
|
12
|
+
def self.make_rng(seed = nil)
|
13
|
+
# if not explicitly provided, seed is taken from the (lower quality)
|
14
|
+
# pseudo-random Kernel::rand generator
|
15
|
+
if RUBY_PLATFORM == 'java'
|
16
|
+
# this is a somewhat ugly workaround in order to avoid ambibuities in
|
17
|
+
# the constructor method that will be called (we basically explicit the
|
18
|
+
# signature of the constructor that we want to use)
|
19
|
+
constructor = org.apache.commons.math3.random.MersenneTwister.java_class.constructor(Java::long)
|
20
|
+
rng = constructor.new_instance(seed || Kernel::rand(2**31 - 1))
|
21
|
+
else
|
22
|
+
rng = seed ?
|
23
|
+
GSL::Rng.alloc(GSL::Rng::MT19937, seed) :
|
24
|
+
GSL::Rng.alloc(GSL::Rng::MT19937, Kernel::rand(2**31 - 1))
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
##
|
2
|
+
# Object#try extension
|
3
|
+
#
|
4
|
+
# From rails:
|
5
|
+
# * https://github.com/rails/rails/blob/master/activesupport/lib/active_support/core_ext/object/try.rb
|
6
|
+
|
7
|
+
class Object
|
8
|
+
alias_method :try, :__send__
|
9
|
+
end
|
10
|
+
|
11
|
+
class NilClass
|
12
|
+
def try(*args)
|
13
|
+
nil
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
if RUBY_PLATFORM == 'java'
|
2
|
+
require 'java'
|
3
|
+
java_import org.apache.commons.math3.distribution.UniformRealDistribution
|
4
|
+
end
|
5
|
+
|
6
|
+
require 'erv/distribution'
|
7
|
+
require 'erv/support/try'
|
8
|
+
|
9
|
+
|
10
|
+
module ERV
|
11
|
+
|
12
|
+
class UniformDistribution < Distribution
|
13
|
+
def initialize(opts)
|
14
|
+
super(opts)
|
15
|
+
|
16
|
+
raise ArgumentError unless opts[:max_value]
|
17
|
+
max = opts[:max_value].to_f
|
18
|
+
min = opts[:min_value].try(:to_f) || 0.0
|
19
|
+
|
20
|
+
if RUBY_PLATFORM == 'java'
|
21
|
+
# create distribution
|
22
|
+
d = UniformRealDistribution.new(@rng, min, max,
|
23
|
+
UniformRealDistribution::DEFAULT_INVERSE_ABSOLUTE_ACCURACY)
|
24
|
+
# setup sampling function
|
25
|
+
@func = Proc.new { d.sample }
|
26
|
+
else
|
27
|
+
# setup sampling function
|
28
|
+
@func = Proc.new { @rng.flat(min, max) }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/erv/version.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'erv/constant_distribution'
|
4
|
+
|
5
|
+
describe ERV::ConstantDistribution do
|
6
|
+
|
7
|
+
it 'should require a reference value' do
|
8
|
+
lambda do
|
9
|
+
ERV::ConstantDistribution.new
|
10
|
+
end.should raise_error
|
11
|
+
end
|
12
|
+
|
13
|
+
context 'reference value' do
|
14
|
+
|
15
|
+
it 'should be accepted at initialization time' do
|
16
|
+
lambda do
|
17
|
+
ERV::ConstantDistribution.new(value: 10)
|
18
|
+
end.should_not raise_error
|
19
|
+
end
|
20
|
+
|
21
|
+
it 'should match the value returned by sampling' do
|
22
|
+
val = rand(100)
|
23
|
+
crv = ERV::ConstantDistribution.new(value: val)
|
24
|
+
crv.sample.should == val
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
|
6
|
+
# Required to setup classpath for Apache Commons Math 3.3-SNAPSHOT in JRuby
|
7
|
+
require 'erv'
|
8
|
+
|
9
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
10
|
+
RSpec.configure do |config|
|
11
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
12
|
+
config.run_all_when_everything_filtered = true
|
13
|
+
config.filter_run :focus
|
14
|
+
|
15
|
+
# Run specs in random order to surface order dependencies. If you find an
|
16
|
+
# order dependency and want to debug it, you can fix the order by providing
|
17
|
+
# the seed, which is printed after each run.
|
18
|
+
# --seed 1234
|
19
|
+
config.order = 'random'
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: erv
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mauro Tortonesi
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-02-04 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.3'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.3'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - '>='
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - '>='
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: gsl-nmatrix
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
description: erv-0.0.2
|
70
|
+
email:
|
71
|
+
- mauro.tortonesi@unife.it
|
72
|
+
executables: []
|
73
|
+
extensions: []
|
74
|
+
extra_rdoc_files: []
|
75
|
+
files:
|
76
|
+
- Gemfile
|
77
|
+
- LICENSE
|
78
|
+
- README.md
|
79
|
+
- Rakefile
|
80
|
+
- erv.gemspec
|
81
|
+
- lib/erv.rb
|
82
|
+
- lib/erv/constant_distribution.rb
|
83
|
+
- lib/erv/discrete_uniform_distribution.rb
|
84
|
+
- lib/erv/distribution.rb
|
85
|
+
- lib/erv/exponential_distribution.rb
|
86
|
+
- lib/erv/gamma_distribution.rb
|
87
|
+
- lib/erv/gaussian_distribution.rb
|
88
|
+
- lib/erv/general_pareto_distribution.rb
|
89
|
+
- lib/erv/geometric_distribution.rb
|
90
|
+
- lib/erv/random_variable.rb
|
91
|
+
- lib/erv/rng.rb
|
92
|
+
- lib/erv/support/try.rb
|
93
|
+
- lib/erv/uniform_distribution.rb
|
94
|
+
- lib/erv/version.rb
|
95
|
+
- spec/erv/constant_distribution_spec.rb
|
96
|
+
- spec/spec_helper.rb
|
97
|
+
homepage: https://github.com/mtortonesi/ruby-erv
|
98
|
+
licenses:
|
99
|
+
- MIT
|
100
|
+
metadata: {}
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options: []
|
103
|
+
require_paths:
|
104
|
+
- lib
|
105
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - '>='
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - '>='
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
requirements: []
|
116
|
+
rubyforge_project:
|
117
|
+
rubygems_version: 2.1.11
|
118
|
+
signing_key:
|
119
|
+
specification_version: 4
|
120
|
+
summary: Easy/elegant Ruby library providing support for random variable generation
|
121
|
+
test_files:
|
122
|
+
- spec/erv/constant_distribution_spec.rb
|
123
|
+
- spec/spec_helper.rb
|