Class: GamesDice::Probabilities
- Inherits:
-
Object
- Object
- GamesDice::Probabilities
- Defined in:
- lib/games_dice/marshal.rb,
ext/games_dice/probabilities.c
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.
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.
Instance Method Summary collapse
-
#each {|result, probability| ... } ⇒ GamesDice::Probabilities
Iterates through value, probability pairs.
-
#expected ⇒ Float
Expected value of distribution.
-
#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, offset) ⇒ GamesDice::Probabilities
constructor
Creates new instance of GamesDice::Probabilities.
-
#clone ⇒ GamesDice::Probabilities
Cloning an object of this class creates a deep copy of the probabilities hash.
-
#max ⇒ Integer
Maximum result in the distribution.
-
#min ⇒ Integer
Minimum result in the distribution.
-
#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, offset) ⇒ GamesDice::Probabilities
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 |
# File 'ext/games_dice/probabilities.c', line 584
VALUE probabilities_initialize( VALUE self, VALUE arr, VALUE offset ) {
int i, o, s;
double error, p_item;
ProbabilityList *pl;
double *pr;
o = NUM2INT(offset);
Check_Type( arr, T_ARRAY );
s = FIX2INT( rb_funcall( arr, rb_intern("count"), 0 ) );
pl = get_probability_list( self );
pl->offset = o;
pr = alloc_probs( pl, s );
for(i=0; i<s; i++) {
p_item = NUM2DBL( rb_ary_entry( arr, i ) );
if ( p_item < 0.0 ) {
rb_raise( rb_eArgError, "Negative probability not allowed" );
} else if ( p_item > 1.0 ) {
rb_raise( rb_eArgError, "Probability must be in range 0.0..1.0" );
}
pr[i] = p_item;
}
error = calc_cumulative( pl ) - 1.0;
if ( error < -1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are less than 1.0" );
} else if ( error > 1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are greater than 1.0" );
}
return self;
}
|
Class Method Details
.add_distributions(pd_a, pd_b) ⇒ GamesDice::Probabilities
889 890 891 892 893 894 895 896 897 |
# File 'ext/games_dice/probabilities.c', line 889
VALUE probabilities_add_distributions( VALUE self, VALUE gdpa, VALUE gdpb ) {
ProbabilityList *pl_a = get_probability_list( gdpa );
ProbabilityList *pl_b = get_probability_list( gdpb );
assert_value_wraps_pl( gdpa );
assert_value_wraps_pl( gdpb );
pl_a = get_probability_list( gdpa );
pl_b = get_probability_list( gdpb );
return pl_as_ruby_class( pl_add_distributions( pl_a, pl_b ), Probabilities );
}
|
.add_distributions_mult(m_a, pd_a, m_b, pd_b) ⇒ GamesDice::Probabilities
909 910 911 912 913 914 915 916 917 918 919 920 921 |
# File 'ext/games_dice/probabilities.c', line 909
VALUE probabilities_add_distributions_mult( VALUE self, VALUE m_a, VALUE gdpa, VALUE m_b, VALUE gdpb ) {
int mul_a, mul_b;
ProbabilityList *pl_a;
ProbabilityList *pl_b;
assert_value_wraps_pl( gdpa );
assert_value_wraps_pl( gdpb );
mul_a = NUM2INT( m_a );
pl_a = get_probability_list( gdpa );
mul_b = NUM2INT( m_b );
pl_b = get_probability_list( gdpb );
return pl_as_ruby_class( pl_add_distributions_mult( mul_a, pl_a, mul_b, pl_b ), Probabilities );
}
|
.for_fair_die(sides) ⇒ GamesDice::Probabilities
Distribution for a die with equal chance of rolling 1..N
826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 |
# File 'ext/games_dice/probabilities.c', line 826
VALUE probabilities_for_fair_die( VALUE self, VALUE sides ) {
int s = NUM2INT( sides );
VALUE obj;
ProbabilityList *pl;
if ( s < 1 ) {
rb_raise( rb_eArgError, "Number of sides should be 1 or more" );
}
if ( s > 100000 ) {
rb_raise( rb_eArgError, "Number of sides should be less than 100001" );
}
obj = pl_alloc( Probabilities );
pl = get_probability_list( obj );
pl->offset = 1;
alloc_probs_iv( pl, s, 1.0/s );
return obj;
}
|
.from_h(prob_hash) ⇒ GamesDice::Probabilities
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 |
# File 'ext/games_dice/probabilities.c', line 851
VALUE probabilities_from_h( VALUE self, VALUE hash ) {
VALUE obj;
ProbabilityList *pl;
double error;
Check_Type( hash, T_HASH );
obj = pl_alloc( Probabilities );
pl = get_probability_list( obj );
// Set these up so that they get adjusted during hash iteration
pl->offset = 0x7fffffff;
pl->slots = 0;
// First iteration establish min/max and validate all key/values
rb_hash_foreach( hash, validate_key_value, obj );
alloc_probs_iv( pl, pl->slots, 0.0 );
// Second iteration copy key/value pairs into structure
rb_hash_foreach( hash, copy_key_value, obj );
error = calc_cumulative( pl ) - 1.0;
if ( error < -1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are less than 1.0" );
} else if ( error > 1.0e-8 ) {
rb_raise( rb_eArgError, "Total probabilities are greater than 1.0" );
}
return obj;
}
|
Instance Method Details
#each {|result, probability| ... } ⇒ GamesDice::Probabilities
Iterates through value, probability pairs
805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 |
# File 'ext/games_dice/probabilities.c', line 805
VALUE probabilities_each( VALUE self ) {
ProbabilityList *pl = get_probability_list( self );
int i;
double *pr = pl->probs;
int o = pl->offset;
for ( i = 0; i < pl->slots; i++ ) {
if ( pr[i] > 0.0 ) {
VALUE a = rb_ary_new2( 2 );
rb_ary_store( a, 0, INT2NUM( i + o ));
rb_ary_store( a, 1, DBL2NUM( pr[i] ));
rb_yield( a );
}
}
return self;
}
|
#expected ⇒ Float
728 729 730 |
# File 'ext/games_dice/probabilities.c', line 728 VALUE probabilites_expected( VALUE self ) { return DBL2NUM( pl_expected( get_probability_list( self ) ) ); } |
#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.
738 739 740 741 742 |
# File 'ext/games_dice/probabilities.c', line 738
VALUE probabilities_given_ge( VALUE self, VALUE target ) {
int t = NUM2INT(target);
ProbabilityList *pl = get_probability_list( self );
return pl_as_ruby_class( pl_given_ge( pl, t ), Probabilities );
}
|
#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.
750 751 752 753 754 |
# File 'ext/games_dice/probabilities.c', line 750
VALUE probabilities_given_le( VALUE self, VALUE target ) {
int t = NUM2INT(target);
ProbabilityList *pl = get_probability_list( self );
return pl_as_ruby_class( pl_given_le( pl, t ), Probabilities );
}
|
#clone ⇒ GamesDice::Probabilities
619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 |
# File 'ext/games_dice/probabilities.c', line 619
VALUE probabilities_initialize_copy( VALUE copy, VALUE orig ) {
ProbabilityList *pl_copy;
ProbabilityList *pl_orig;
double *pr;
if (copy == orig) return copy;
pl_copy = get_probability_list( copy );
pl_orig = get_probability_list( orig );
pr = alloc_probs( pl_copy, pl_orig->slots );
pl_copy->offset = pl_orig->offset;
memcpy( pr, pl_orig->probs, pl_orig->slots * sizeof(double) );
memcpy( pl_copy->cumulative, pl_orig->cumulative, pl_orig->slots * sizeof(double) );;
return copy;
}
|
#max ⇒ Integer
673 674 675 |
# File 'ext/games_dice/probabilities.c', line 673 VALUE probabilities_max( VALUE self ) { return INT2NUM( pl_max( get_probability_list( self ) ) ); } |
#min ⇒ Integer
663 664 665 |
# File 'ext/games_dice/probabilities.c', line 663 VALUE probabilities_min( VALUE self ) { return INT2NUM( pl_min( get_probability_list( self ) ) ); } |
#p_eql(target) ⇒ Float
Probability of result equalling specific target
682 683 684 |
# File 'ext/games_dice/probabilities.c', line 682
VALUE probabilites_p_eql( VALUE self, VALUE target ) {
return DBL2NUM( pl_p_eql( get_probability_list( self ), NUM2INT(target) ) );
}
|
#p_ge(target) ⇒ Float
Probability of result being equal to or greater than specific target
700 701 702 |
# File 'ext/games_dice/probabilities.c', line 700
VALUE probabilites_p_ge( VALUE self, VALUE target ) {
return DBL2NUM( pl_p_ge( get_probability_list( self ), NUM2INT(target) ) );
}
|
#p_gt(target) ⇒ Float
Probability of result being greater than specific target
691 692 693 |
# File 'ext/games_dice/probabilities.c', line 691
VALUE probabilites_p_gt( VALUE self, VALUE target ) {
return DBL2NUM( pl_p_gt( get_probability_list( self ), NUM2INT(target) ) );
}
|
#p_le(target) ⇒ Float
Probability of result being equal to or less than specific target
709 710 711 |
# File 'ext/games_dice/probabilities.c', line 709
VALUE probabilites_p_le( VALUE self, VALUE target ) {
return DBL2NUM( pl_p_le( get_probability_list( self ), NUM2INT(target) ) );
}
|
#p_lt(target) ⇒ Float
Probability of result being less than specific target
718 719 720 |
# File 'ext/games_dice/probabilities.c', line 718
VALUE probabilites_p_lt( VALUE self, VALUE target ) {
return DBL2NUM( pl_p_lt( get_probability_list( self ), NUM2INT(target) ) );
}
|
#repeat_n_sum_k(n, k, kmode = :keep_best) ⇒ GamesDice::Probabilities
777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 |
# File 'ext/games_dice/probabilities.c', line 777
VALUE probabilities_repeat_n_sum_k( int argc, VALUE* argv, VALUE self ) {
VALUE nsum, nkeepers, kmode;
int keep_best, n, k;
ProbabilityList *pl;
rb_scan_args( argc, argv, "21", &nsum, &nkeepers, &kmode );
keep_best = 1;
if (NIL_P(kmode)) {
keep_best = 1;
} else if ( rb_intern("keep_worst") == SYM2ID(kmode) ) {
keep_best = 0;
} else if ( rb_intern("keep_best") != SYM2ID(kmode) ) {
rb_raise( rb_eArgError, "Keep mode not recognised" );
}
n = NUM2INT(nsum);
k = NUM2INT(nkeepers);
pl = get_probability_list( self );
return pl_as_ruby_class( pl_repeat_n_sum_k( pl, n, k, keep_best ), Probabilities );
}
|
#repeat_sum(n) ⇒ GamesDice::Probabilities
763 764 765 766 767 |
# File 'ext/games_dice/probabilities.c', line 763
VALUE probabilities_repeat_sum( VALUE self, VALUE nsum ) {
int n = NUM2INT(nsum);
ProbabilityList *pl = get_probability_list( self );
return pl_as_ruby_class( pl_repeat_sum( pl, n ), Probabilities );
}
|
#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.
642 643 644 645 646 647 648 649 650 651 652 653 654 655 |
# File 'ext/games_dice/probabilities.c', line 642
VALUE probabilities_to_h( VALUE self ) {
ProbabilityList *pl = get_probability_list( self );
VALUE h = rb_hash_new();
double *pr = pl->probs;
int s = pl->slots;
int o = pl->offset;
int i;
for(i=0; i<s; i++) {
if ( pr[i] > 0.0 ) {
rb_hash_aset( h, INT2FIX( o + i ), DBL2NUM( pr[i] ) );
}
}
return h;
}
|