monte_carlo 0.0.1

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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ba714d8eb65cabff56fc508ab075c62e0afaf188
4
+ data.tar.gz: 0b5910159859348ebab617e7abc1ccb9e23ce18d
5
+ SHA512:
6
+ metadata.gz: 944b151e94f22a06db7ff167ee71897ea57436448c7e37dcf7dfcb0440e0aa34e050264183f2e03e5ae6d428b4a86820dd0c156fb5176d16c542e22453ed3596
7
+ data.tar.gz: c2aae5f7d6a5ddafcbbea7bf54995d2180f6c0a1e7144541cffcbb1c61090ee99fc9a697adabe6f6cdb9d1cf340cdf7c0b0ff32e4d855776cf5efd7bc62ffe3e
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in monte_carlo.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Assaf Gelber
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 ADDED
@@ -0,0 +1,65 @@
1
+ # MonteCarlo
2
+
3
+ A utility to write quick [Monte Carlo Method](http://en.wikipedia.org/wiki/Monte_Carlo_method) experiments.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'monte_carlo'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install monte_carlo
20
+
21
+ ## Usage
22
+
23
+ Each experiment conatins:
24
+ - `times`: the number of sample to create (defaults to 10,000)
25
+ - `sample_method`: the method with which to generate a sample each iteration
26
+ - `computation`: an optional coputation method to run on each sample to obtain a result
27
+
28
+ For example;
29
+
30
+ ```ruby
31
+ # Create an experiment with an optional number of times
32
+ experiment = MonteCarlo::Experiment.new(100000)
33
+
34
+ # Set your smaple method
35
+ experiment.sample_method = -> { rand }
36
+
37
+ # Set your optional computation method
38
+ experiment.computation = -> (sample) { sample > 0.5 }
39
+
40
+ # Run your experiment and get your results
41
+ results = experiment.run
42
+ ```
43
+
44
+ Alternatively, you can write your sample and computation method as one with the shorthand block syntax:
45
+
46
+ ```ruby
47
+ results = MonteCarlo::Experiment.run(100000) { rand > 0.5 }
48
+ ```
49
+
50
+ The experiment returns a `MonteCarlo::ExperimentResults` object which contains an array of `MonteCarlo::Results` as well as some other handy methods.
51
+
52
+ Each `MonteCarlo::Result` contains:
53
+ - `index`: the index of the sample
54
+ - `value`: the final value returned from sampling, after computation
55
+ - `sample_value`: the value returned from the sample method, before computation
56
+
57
+ If no computation method was given, `value` and `sample_value` will be the same.
58
+
59
+ ## Contributing
60
+
61
+ 1. Fork it ( https://github.com/[agelber]/monte_carlo/fork )
62
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
63
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
64
+ 4. Push to the branch (`git push origin my-new-feature`)
65
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ require 'rspec/core/rake_task'
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :test => :spec
7
+ task :default => :spec
@@ -0,0 +1,8 @@
1
+ require "monte_carlo/version"
2
+ require "monte_carlo/errors"
3
+ require "monte_carlo/result"
4
+ require "monte_carlo/experiment_results"
5
+ require "monte_carlo/experiment"
6
+
7
+ module MonteCarlo
8
+ end
@@ -0,0 +1,7 @@
1
+ module MonteCarlo
2
+ module Errors
3
+
4
+ class NoSampleMethodError < StandardError; end
5
+
6
+ end
7
+ end
@@ -0,0 +1,46 @@
1
+ module MonteCarlo
2
+ class Experiment
3
+
4
+ DEFAULT_TIMES = 10000
5
+
6
+ attr_accessor :times, :sample_method, :computation
7
+
8
+ def self.run(times = DEFAULT_TIMES, &block)
9
+ MonteCarlo::Experiment.new(times, &block).run
10
+ end
11
+
12
+ def initialize(times = DEFAULT_TIMES, &block)
13
+ @times = times
14
+ @sample_method = block
15
+ end
16
+
17
+ def run
18
+ if @sample_method.nil?
19
+ raise MonteCarlo::Errors::NoSampleMethodError, 'A sample method for this experiment is not defined'
20
+ end
21
+
22
+ results = MonteCarlo::ExperimentResults.new
23
+
24
+ @times.times do |index|
25
+ results << run_sample(index)
26
+ end
27
+
28
+ results
29
+ end
30
+
31
+ private
32
+
33
+ def run_sample(index)
34
+ result = MonteCarlo::Result.new(index)
35
+ result.sample_value = @sample_method.call()
36
+ if @computation.nil?
37
+ result.value = result.sample_value
38
+ else
39
+ result.value = @computation.call(result.sample_value)
40
+ end
41
+
42
+ result
43
+ end
44
+
45
+ end
46
+ end
@@ -0,0 +1,53 @@
1
+ module MonteCarlo
2
+ class ExperimentResults
3
+ include Enumerable
4
+
5
+ def initialize
6
+ @results = []
7
+ end
8
+
9
+ def each(&block)
10
+ @results.each do |result|
11
+ block_given? ? block.call(result) : yield(result)
12
+ end
13
+ end
14
+
15
+ def << result
16
+ @results << result
17
+ reset_memoizers
18
+ end
19
+
20
+ def size
21
+ @results.size
22
+ end
23
+
24
+ def probability_distribution
25
+ @probability_distribution ||= @results.group_by(&:value).inject({}) do |probabilites, (value, results)|
26
+ probabilites[value] = results.size.to_f / self.size
27
+ probabilites
28
+ end
29
+ end
30
+
31
+ def frequency_distribution
32
+ @frequency_distribution ||= @results.group_by(&:value).inject({}) do |frequencies, (value, results)|
33
+ frequencies[value] = results.size
34
+ frequencies
35
+ end
36
+ end
37
+
38
+ def probability_of(value)
39
+ probability_distribution.fetch(value, 0)
40
+ end
41
+
42
+ def frequency_of(value)
43
+ frequency_distribution.fetch(value, 0)
44
+ end
45
+
46
+ private
47
+
48
+ def reset_memoizers
49
+ @probability_distribution = nil
50
+ @frequency_distribution = nil
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,22 @@
1
+ module MonteCarlo
2
+ class Result
3
+ include Comparable
4
+
5
+ attr_accessor :value, :sample_value, :index
6
+
7
+ def initialize(index = nil, value = nil, sample_value = nil)
8
+ @value = value
9
+ @sample_value = sample_value
10
+ @index = index
11
+ end
12
+
13
+ def <=> other
14
+ self.to_i <=> other.to_i
15
+ end
16
+
17
+ def to_i
18
+ @value
19
+ end
20
+
21
+ end
22
+ end
@@ -0,0 +1,3 @@
1
+ module MonteCarlo
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'monte_carlo/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "monte_carlo"
8
+ spec.version = MonteCarlo::VERSION
9
+ spec.authors = ["Assaf Gelber"]
10
+ spec.email = ["assaf.gelber@gmail.com"]
11
+ spec.summary = %q{A small gem to help with Monte Carlo Method experiments in ruby.}
12
+ spec.description = %q{A small gem to help with Monte Carlo Method experiments in ruby.}
13
+ spec.homepage = "https://github.com/agelber/monte_carlo"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
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.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+ spec.add_development_dependency "rspec", "~> 3.1"
24
+ spec.add_development_dependency "rspec-its"
25
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe MonteCarlo::ExperimentResults do
4
+
5
+ let(:times) { 99 }
6
+ let(:results) do
7
+ results = MonteCarlo::ExperimentResults.new
8
+ times.times do |index|
9
+ results << MonteCarlo::Result.new(index, index % 3 == 0)
10
+ end
11
+ results
12
+ end
13
+
14
+ shared_examples_for :of_methdds do |method|
15
+ it 'returns 0 when the value does not exist' do
16
+ expect(results.send(method, 'does not exist')).to eq 0
17
+ end
18
+ end
19
+
20
+ describe :probability_distribution do
21
+ it 'should return the correct probability distribution for the results' do
22
+ expect(results.probability_distribution.keys).to contain_exactly(true, false)
23
+ expect(results.probability_distribution[true]).to eq 1 / 3.0
24
+ expect(results.probability_distribution[false]).to eq 2 / 3.0
25
+ end
26
+ end
27
+
28
+ describe :frequency_distribution do
29
+ it 'should return the correct frequency distribution for the results' do
30
+ expect(results.frequency_distribution.keys).to contain_exactly(true, false)
31
+ expect(results.frequency_distribution[true]).to eq 33
32
+ expect(results.frequency_distribution[false]).to eq 66
33
+ end
34
+ end
35
+
36
+ describe :probability_of do
37
+ it_behaves_like :of_methdds, :probability_of
38
+
39
+ it 'should return the correct probability of a value' do
40
+ expect(results.probability_of(true)).to eq 1 / 3.0
41
+ end
42
+ end
43
+
44
+ describe :frequency_of do
45
+ it_behaves_like :of_methdds, :frequency_of
46
+
47
+ it 'should return the correct frequency of a value' do
48
+ expect(results.frequency_of(true)).to eq 33
49
+ end
50
+ end
51
+
52
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe MonteCarlo::Experiment do
4
+
5
+ let(:times) { 1000 }
6
+ let(:sample_value) { 1 }
7
+ let(:computation) { -> (sample) {sample * 2} }
8
+ let(:experiment) do
9
+ experiment = MonteCarlo::Experiment.new
10
+ experiment.times = 1000
11
+ experiment.sample_method = -> { sample_value }
12
+ experiment.computation = computation
13
+ experiment
14
+ end
15
+
16
+ describe :run do
17
+ it 'should raise a NoSampleMethodError if a sample method is not defined' do
18
+ experiment.sample_method = nil
19
+ expect {
20
+ experiment.run
21
+ }.to raise_error MonteCarlo::Errors::NoSampleMethodError
22
+ end
23
+
24
+ it 'should call the sample_method the correct number of times' do
25
+ sample_double = double(call: sample_value)
26
+ experiment.sample_method = sample_double
27
+ expect(sample_double).to receive(:call).exactly(times).times
28
+ experiment.run
29
+ end
30
+
31
+ it 'should return an array of result objects' do
32
+ results = experiment.run
33
+ expect(results).to all( be_a MonteCarlo::Result )
34
+ end
35
+
36
+ it 'should return results with correct sample values' do
37
+ results = experiment.run
38
+ expect(results.map(&:sample_value)).to all( eq sample_value)
39
+ end
40
+
41
+ it 'should return results with correct values' do
42
+ results = experiment.run
43
+ expect(results.map(&:value)).to all( eq computation.call(sample_value))
44
+ end
45
+ end
46
+
47
+ end
@@ -0,0 +1,8 @@
1
+ require 'bundler/setup'
2
+ Bundler.setup
3
+
4
+ require 'monte_carlo'
5
+
6
+ RSpec.configure do |config|
7
+ config.color = true
8
+ end
metadata ADDED
@@ -0,0 +1,118 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: monte_carlo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Assaf Gelber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-29 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.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.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: '3.1'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-its
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: A small gem to help with Monte Carlo Method experiments in ruby.
70
+ email:
71
+ - assaf.gelber@gmail.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - .gitignore
77
+ - Gemfile
78
+ - LICENSE.txt
79
+ - README.md
80
+ - Rakefile
81
+ - lib/monte_carlo.rb
82
+ - lib/monte_carlo/errors.rb
83
+ - lib/monte_carlo/experiment.rb
84
+ - lib/monte_carlo/experiment_results.rb
85
+ - lib/monte_carlo/result.rb
86
+ - lib/monte_carlo/version.rb
87
+ - monte_carlo.gemspec
88
+ - spec/lib/monte_carlo/experiment_results_spec.rb
89
+ - spec/lib/monte_carlo/experiment_spec.rb
90
+ - spec/spec_helper.rb
91
+ homepage: https://github.com/agelber/monte_carlo
92
+ licenses:
93
+ - MIT
94
+ metadata: {}
95
+ post_install_message:
96
+ rdoc_options: []
97
+ require_paths:
98
+ - lib
99
+ required_ruby_version: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - '>='
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ requirements: []
110
+ rubyforge_project:
111
+ rubygems_version: 2.4.2
112
+ signing_key:
113
+ specification_version: 4
114
+ summary: A small gem to help with Monte Carlo Method experiments in ruby.
115
+ test_files:
116
+ - spec/lib/monte_carlo/experiment_results_spec.rb
117
+ - spec/lib/monte_carlo/experiment_spec.rb
118
+ - spec/spec_helper.rb