Class: GamesDice::Probabilities
- Inherits:
-
Object
- Object
- GamesDice::Probabilities
- Defined in:
- lib/games_dice/probabilities.rb,
lib/games_dice/marshal.rb
Overview
This class models probability distributions for dice systems.
An object of this class represents a single distribution, which might be the result of a complex combination of dice.
Instance Attribute Summary collapse
-
#expected ⇒ Float
readonly
Expected value of distribution.
-
#max ⇒ Integer
readonly
Maximum result in the distribution.
-
#min ⇒ Integer
readonly
Minimum result in the distribution.
Class Method Summary collapse
-
.add_distributions(pd_a, pd_b) ⇒ GamesDice::Probabilities
Combines two distributions to create a third, that represents the distribution created when adding results together.
-
.add_distributions_mult(m_a, pd_a, m_b, pd_b) ⇒ GamesDice::Probabilities
Combines two distributions with multipliers to create a third, that represents the distribution created when adding weighted results together.
-
.for_fair_die(sides) ⇒ GamesDice::Probabilities
Distribution for a die with equal chance of rolling 1..N.
-
.from_h(prob_hash) ⇒ GamesDice::Probabilities
Creates new instance of GamesDice::Probabilities.
-
.implemented_in ⇒ Symbol
Returns a symbol for the language name that this class is implemented in.
Instance Method Summary collapse
-
#each {|result, probability| ... } ⇒ GamesDice::Probabilities
Iterates through value, probability pairs.
-
#given_ge(target) ⇒ GamesDice::Probabilities
Probability distribution derived from this one, where we know (or are only interested in situations where) the result is greater than or equal to target.
-
#given_le(target) ⇒ GamesDice::Probabilities
Probability distribution derived from this one, where we know (or are only interested in situations where) the result is less than or equal to target.
-
#initialize(probs = [1.0], offset = 0) ⇒ GamesDice::Probabilities
constructor
Creates new instance of GamesDice::Probabilities.
-
#p_eql(target) ⇒ Float
Probability of result equalling specific target.
-
#p_ge(target) ⇒ Float
Probability of result being equal to or greater than specific target.
-
#p_gt(target) ⇒ Float
Probability of result being greater than specific target.
-
#p_le(target) ⇒ Float
Probability of result being equal to or less than specific target.
-
#p_lt(target) ⇒ Float
Probability of result being less than specific target.
-
#repeat_n_sum_k(n, k, kmode = :keep_best) ⇒ GamesDice::Probabilities
Calculates distribution generated by summing best k results of n iterations of the distribution.
-
#repeat_sum(n) ⇒ GamesDice::Probabilities
Adds a distribution to itself repeatedly, to simulate a number of dice results being summed.
-
#to_h ⇒ Hash
A hash representation of the distribution.
Constructor Details
#initialize(probs = [1.0], offset = 0) ⇒ GamesDice::Probabilities
Creates new instance of GamesDice::Probabilities.
32 33 34 35 36 |
# File 'lib/games_dice/probabilities.rb', line 32 def initialize( probs = [1.0], offset = 0 ) # This should *probably* be validated in future, but that would impact performance @probs = check_probs_array probs.clone @offset = Integer(offset) end |
Instance Attribute Details
#expected ⇒ Float (readonly)
Expected value of distribution.
72 73 74 |
# File 'lib/games_dice/probabilities.rb', line 72 def expected @expected ||= calc_expected end |
#max ⇒ Integer (readonly)
Maximum result in the distribution
65 66 67 |
# File 'lib/games_dice/probabilities.rb', line 65 def max @offset + @probs.count() - 1 end |
#min ⇒ Integer (readonly)
Minimum result in the distribution
58 59 60 |
# File 'lib/games_dice/probabilities.rb', line 58 def min @offset end |
Class Method Details
.add_distributions(pd_a, pd_b) ⇒ GamesDice::Probabilities
Combines two distributions to create a third, that represents the distribution created when adding results together.
178 179 180 181 182 183 184 |
# File 'lib/games_dice/probabilities.rb', line 178 def self.add_distributions pd_a, pd_b check_is_gdp( pd_a, pd_b ) combined_min = pd_a.min + pd_b.min combined_max = pd_a.max + pd_b.max add_distributions_internal( combined_min, combined_max, 1, pd_a, 1, pd_b ) end |
.add_distributions_mult(m_a, pd_a, m_b, pd_b) ⇒ GamesDice::Probabilities
Combines two distributions with multipliers to create a third, that represents the distribution created when adding weighted results together.
193 194 195 196 197 198 199 200 201 |
# File 'lib/games_dice/probabilities.rb', line 193 def self.add_distributions_mult m_a, pd_a, m_b, pd_b check_is_gdp( pd_a, pd_b ) m_a = Integer(m_a) m_b = Integer(m_b) combined_min, combined_max = calc_combined_extremes( m_a, pd_a, m_b, pd_b ).minmax add_distributions_internal( combined_min, combined_max, m_a, pd_a, m_b, pd_b ) end |
.for_fair_die(sides) ⇒ GamesDice::Probabilities
Distribution for a die with equal chance of rolling 1..N
166 167 168 169 170 171 |
# File 'lib/games_dice/probabilities.rb', line 166 def self.for_fair_die sides sides = Integer(sides) raise ArgumentError, "sides must be at least 1" unless sides > 0 raise ArgumentError, "sides can be at most 100000" if sides > 100000 GamesDice::Probabilities.new( Array.new( sides, 1.0/sides ), 1 ) end |
.from_h(prob_hash) ⇒ GamesDice::Probabilities
Creates new instance of GamesDice::Probabilities.
157 158 159 160 161 |
# File 'lib/games_dice/probabilities.rb', line 157 def self.from_h prob_hash raise TypeError, "from_h expected a Hash" unless prob_hash.is_a? Hash probs, offset = prob_h_to_ao( prob_hash ) GamesDice::Probabilities.new( probs, offset ) end |
.implemented_in ⇒ Symbol
Returns a symbol for the language name that this class is implemented in. The C version of the code is noticeably faster when dealing with larger numbers of possible results.
206 207 208 |
# File 'lib/games_dice/probabilities.rb', line 206 def self.implemented_in :ruby end |
Instance Method Details
#each {|result, probability| ... } ⇒ GamesDice::Probabilities
Iterates through value, probability pairs
42 43 44 45 |
# File 'lib/games_dice/probabilities.rb', line 42 def each @probs.each_with_index { |p,i| yield( i+@offset, p ) if p > 0.0 } return self end |
#given_ge(target) ⇒ GamesDice::Probabilities
Probability distribution derived from this one, where we know (or are only interested in situations where) the result is greater than or equal to target.
129 130 131 132 133 134 135 136 137 |
# File 'lib/games_dice/probabilities.rb', line 129 def given_ge target target = Integer(target) target = min if min > target p = p_ge(target) raise "There is no valid distribution given a result >= #{target}" unless p > 0.0 mult = 1.0/p new_probs = @probs[target-@offset,@probs.count-1].map { |x| x * mult } GamesDice::Probabilities.new( new_probs, target ) end |
#given_le(target) ⇒ GamesDice::Probabilities
Probability distribution derived from this one, where we know (or are only interested in situations where) the result is less than or equal to target.
143 144 145 146 147 148 149 150 151 |
# File 'lib/games_dice/probabilities.rb', line 143 def given_le target target = Integer(target) target = max if max < target p = p_le(target) raise "There is no valid distribution given a result <= #{target}" unless p > 0.0 mult = 1.0/p new_probs = @probs[0..target-@offset].map { |x| x * mult } GamesDice::Probabilities.new( new_probs, @offset ) end |
#p_eql(target) ⇒ Float
Probability of result equalling specific target
79 80 81 82 83 |
# File 'lib/games_dice/probabilities.rb', line 79 def p_eql target i = Integer(target) - @offset return 0.0 if i < 0 || i >= @probs.count @probs[ i ] end |
#p_ge(target) ⇒ Float
Probability of result being equal to or greater than specific target
95 96 97 98 99 100 101 102 103 |
# File 'lib/games_dice/probabilities.rb', line 95 def p_ge target target = Integer(target) return @prob_ge[target] if @prob_ge && @prob_ge[target] @prob_ge = {} unless @prob_ge return 1.0 if target <= min return 0.0 if target > max @prob_ge[target] = @probs[target-@offset,@probs.count-1].inject(0.0) {|so_far,p| so_far + p } end |
#p_gt(target) ⇒ Float
Probability of result being greater than specific target
88 89 90 |
# File 'lib/games_dice/probabilities.rb', line 88 def p_gt target p_ge( Integer(target) + 1 ) end |
#p_le(target) ⇒ Float
Probability of result being equal to or less than specific target
108 109 110 111 112 113 114 115 116 |
# File 'lib/games_dice/probabilities.rb', line 108 def p_le target target = Integer(target) return @prob_le[target] if @prob_le && @prob_le[target] @prob_le = {} unless @prob_le return 1.0 if target >= max return 0.0 if target < min @prob_le[target] = @probs[0,1+target-@offset].inject(0.0) {|so_far,p| so_far + p } end |
#p_lt(target) ⇒ Float
Probability of result being less than specific target
121 122 123 |
# File 'lib/games_dice/probabilities.rb', line 121 def p_lt target p_le( Integer(target) - 1 ) end |
#repeat_n_sum_k(n, k, kmode = :keep_best) ⇒ GamesDice::Probabilities
Calculates distribution generated by summing best k results of n iterations of the distribution.
226 227 228 229 230 231 232 233 234 |
# File 'lib/games_dice/probabilities.rb', line 226 def repeat_n_sum_k n, k, kmode = :keep_best n = Integer( n ) k = Integer( k ) raise "Cannot combine probabilities less than once" if n < 1 # Technically this is a limitation of C code, but Ruby version is most likely slow and inaccurate beyond 170 raise "Too many dice to calculate numbers of arrangements" if n > 170 check_keep_mode( kmode ) repeat_n_sum_k_internal( n, k, kmode ) end |
#repeat_sum(n) ⇒ GamesDice::Probabilities
Adds a distribution to itself repeatedly, to simulate a number of dice results being summed.
214 215 216 217 218 219 |
# File 'lib/games_dice/probabilities.rb', line 214 def repeat_sum n n = Integer( n ) raise "Cannot combine probabilities less than once" if n < 1 raise "Probability distribution too large" if ( n * @probs.count ) > 1000000 repeat_sum_internal( n ) end |
#to_h ⇒ Hash
A hash representation of the distribution. Each key is an integer result, and the matching value is probability of getting that result. A new hash is generated on each call to this method.
51 52 53 |
# File 'lib/games_dice/probabilities.rb', line 51 def to_h GamesDice::Probabilities.prob_ao_to_h( @probs, @offset ) end |