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
613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 |
# File 'ext/games_dice/probabilities.c', line 613
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
918 919 920 921 922 923 924 925 926 927 |
# File 'ext/games_dice/probabilities.c', line 918
VALUE probabilities_add_distributions( VALUE self, VALUE gdpa, VALUE gdpb ) {
ProbabilityList *pl_a;
ProbabilityList *pl_b;
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
939 940 941 942 943 944 945 946 947 948 949 950 951 |
# File 'ext/games_dice/probabilities.c', line 939
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
855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 |
# File 'ext/games_dice/probabilities.c', line 855
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
880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 |
# File 'ext/games_dice/probabilities.c', line 880
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
834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 |
# File 'ext/games_dice/probabilities.c', line 834
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
757 758 759 |
# File 'ext/games_dice/probabilities.c', line 757 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.
767 768 769 770 771 |
# File 'ext/games_dice/probabilities.c', line 767
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.
779 780 781 782 783 |
# File 'ext/games_dice/probabilities.c', line 779
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
648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 |
# File 'ext/games_dice/probabilities.c', line 648
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
702 703 704 |
# File 'ext/games_dice/probabilities.c', line 702 VALUE probabilities_max( VALUE self ) { return INT2NUM( pl_max( get_probability_list( self ) ) ); } |
#min ⇒ Integer
692 693 694 |
# File 'ext/games_dice/probabilities.c', line 692 VALUE probabilities_min( VALUE self ) { return INT2NUM( pl_min( get_probability_list( self ) ) ); } |
#p_eql(target) ⇒ Float
Probability of result equalling specific target
711 712 713 |
# File 'ext/games_dice/probabilities.c', line 711
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
729 730 731 |
# File 'ext/games_dice/probabilities.c', line 729
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
720 721 722 |
# File 'ext/games_dice/probabilities.c', line 720
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
738 739 740 |
# File 'ext/games_dice/probabilities.c', line 738
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
747 748 749 |
# File 'ext/games_dice/probabilities.c', line 747
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
806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 |
# File 'ext/games_dice/probabilities.c', line 806
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
792 793 794 795 796 |
# File 'ext/games_dice/probabilities.c', line 792
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.
671 672 673 674 675 676 677 678 679 680 681 682 683 684 |
# File 'ext/games_dice/probabilities.c', line 671
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;
}
|